Skip to content

Commit 00cbdaa

Browse files
authored
Merge pull request microsoft#489 from davidxw/profile_pic
Update profile picture for AAD and GH
2 parents 106e0a3 + 2e67b60 commit 00cbdaa

File tree

3 files changed

+77
-17
lines changed

3 files changed

+77
-17
lines changed

docs/2-run-locally.md

+19-11
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,37 @@
11
# 👨🏻‍💻 Run Locally
22

3-
Clone this repository locally or fork to your GitHub account. Run all of the the steps below from the `src` directory.
3+
Clone this repository locally or fork to your GitHub account. Follow the steps below to run the solution locally:
44

55
## Prerequisites
66

7-
- **History Database**: If you don't want to [provision the Azure resources](./4-deploy-to-azure.md), you **must** at least deploy an instance of Azure Cosmos DB in your Azure Subscription to store chat history.
7+
Azure Chat is heavily dependant on a large number of Azure services. The easiest way to deploy all of these required services into an Azure subscription is to use the the [Azure Developer CLI](https://learn.microsoft.com/en-us/azure/developer/azure-developer-cli/overview) as follows:
88

9-
- **Identity Provider**: For local development, you have the option of using a username / password to sign in. If you prefer to use an Identity Provider, follow the [instructions](./3-add-identity.md) in the next chapter to add one.
9+
1. Install the [Azure Developer CLI](https://learn.microsoft.com/en-us/azure/developer/azure-developer-cli/overview)
10+
1. From the root of the repository:
1011

11-
## Steps to Run Locally
12+
1. Run `azd init`
13+
1. Run `azd provision` to provision the Azure resources
14+
15+
16+
## Identity Provider
17+
18+
For local development you can use the `Basic Auth (DEV ONLY)` provider to sign in - this local development identity provider will accept any user name and password, and the username you enter will create a new user id (hash of username@localhost) so you can simulate multiple users. If you prefer to use an Identity Provider (Entra ID or GitHub) for local development follow the [instructions](./3-add-identity.md) in the next chapter to add one.
19+
20+
## Run the App
21+
22+
With the prerequisites complete, follow the steps below to run the solution locally:
1223

1324
1. Change directory to the `src` folder
14-
2. Rename/copy the file `.env.example` to `.env.local` and populate the environment variables based on the deployed resources in Azure.
25+
2. Rename/copy the file `.env.example` to `.env` and populate the environment variables based on the deployed resources in Azure.
1526

16-
> **NOTE**
17-
> If you have used the Azure Developer CLI to deploy the Azure infrastructure required for the solution ([using the directions here](./4-deploy-to-azure.md)), you can find the values for many the required environment variables in the `.env` file the `.azure\<azd env name>` directory. This generated file will not contain any keys, however it is recommended to use managed identities as described in "Setup your local development environment" on [this page](./9-managed-identities.md).
27+
> **NOTE**
28+
> If you have used the Azure Developer CLI to deploy the Azure services required for the solution (as described above), you can find the values for most the required environment variables in the `.env` file the `.azure\<azd env name>` directory. This generated file will not contain any keys, however it is recommended to use managed identities as described in "Run Locally with Managed Identities" on [this page](./9-managed-identities.md).
1829
1930
3. Install npm packages by running `npm install`
2031
4. Start the app by running `npm run dev`
2132
5. Access the app on [http://localhost:3000](http://localhost:3000)
2233

23-
You should now be prompted to log in with your chosen authentication method (per the pre-requisite configuration).
24-
25-
> **NOTE**
26-
> If using Basic Auth (DEV ONLY), any username you enter will create a new user id (hash of username@localhost). You can use this to simulate multiple users. Once successfully logged in, you can start creating new conversations.
34+
You should now be prompted to log in with your chosen authentication method (per your Identity Provider configuration), and you can start chatting.
2735

2836
## Continue to the next step...
2937

docs/9-managed-identities.md

+20-4
Original file line numberDiff line numberDiff line change
@@ -40,15 +40,31 @@ Using Managed Identities is preferred for production deployments due to:
4040

4141
### Deploy to Azure with Managed Identities
4242

43-
To deploy the application to Azure App Service with Managed Identities, follow the standard deployment instructions available in the [Deploy to Azure - GitHub Actions](https://github.com/microsoft/azurechat) section of the repository. Ensure to:
43+
To deploy the application to Azure App Service with Managed Identities, follow the standard deployment instructions available in the [Deploy to Azure - GitHub Actions](https://github.com/microsoft/azurechat) section of the repository as follows:
4444

4545
1. **Update the Parameter**:
4646
- Set the parameter `disableLocalAuth` to `true` in [`infra/main.bicep`](/infra/main.bicep) (or [`infra/main.json`](/infra/main.json) for ARM deployment) to use Managed Identities.
4747
2. **Deploy resources using azd**:
4848
- Refer to the [README](../README.md)
49-
3. **(Optional) Setup your local development environment**:
49+
50+
## Run Locally with Managed Identities
5051

51-
Run this script to grant yourself RBAC permissions on the Azure resources so you can run AzureChat locally with managed identities.
52+
You can run Azure Chat locally with Managed Identities - in this case the identity of the currently logged in user (via `az login`) is used to authenticate with the required Azure services. Follow the steps below to run Azure Chat locally with Managed Identities:
53+
54+
1. Refer to the documentation in [Run Locally](2-run-locally.md) to set up your local environment up for development.
55+
1. Update your `.env` file with the following setting:
56+
```
57+
USE_MANAGED_IDENTITIES=true
58+
```
59+
1. Make sure that your `.env` either has the following settings removed, uncommented, or set to empty. Even though you have set `USE_MANAGED_IDENTITIES=true` the various SDKs that the application uses to interact with these services can still default to key based authentication if these are present:
60+
```
61+
AZURE_OPENAI_API_KEY=
62+
AZURE_OPENAI_DALLE_API_KEY=
63+
AZURE_COSMOSDB_KEY=
64+
AZURE_SEARCH_API_KEY=
65+
AZURE_DOCUMENT_INTELLIGENCE_KEY=
66+
```
67+
1. Run this script to grant yourself RBAC permissions on the various Azure resources used by Azure Chat.
5268

5369
If you haven't already done so then you will need to login to Azure using the Azure CLI command `az login`
5470
- In Powershell:
@@ -60,7 +76,7 @@ To deploy the application to Azure App Service with Managed Identities, follow t
6076
> chmod +x .\scripts\add_localdev_roles.sh
6177
> .\scripts\add_localdev_roles.sh
6278
```
63-
You can now refer to the documentation to [run Azure Chat locally](2-run-locally.md).
79+
6480
6581
## Conclusion
6682

src/features/auth-page/auth-api.ts

+38-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import CredentialsProvider from "next-auth/providers/credentials";
44
import GitHubProvider from "next-auth/providers/github";
55
import { Provider } from "next-auth/providers/index";
66
import { hashValue } from "./helpers";
7+
import { image } from "@markdoc/markdoc/dist/src/schema";
8+
import { access } from "fs";
79

810
const configureIdentityProvider = () => {
911
const providers: Array<Provider> = [];
@@ -18,10 +20,13 @@ const configureIdentityProvider = () => {
1820
clientId: process.env.AUTH_GITHUB_ID!,
1921
clientSecret: process.env.AUTH_GITHUB_SECRET!,
2022
async profile(profile) {
23+
const image = await fetchProfilePicture(profile.avatar_url, null);
2124
const newProfile = {
2225
...profile,
2326
isAdmin: adminEmails?.includes(profile.email.toLowerCase()),
27+
image: image,
2428
};
29+
console.log("GitHub profile:", newProfile);
2530
return newProfile;
2631
},
2732
})
@@ -38,17 +43,24 @@ const configureIdentityProvider = () => {
3843
clientId: process.env.AZURE_AD_CLIENT_ID!,
3944
clientSecret: process.env.AZURE_AD_CLIENT_SECRET!,
4045
tenantId: process.env.AZURE_AD_TENANT_ID!,
41-
async profile(profile) {
46+
authorization: {
47+
params: {
48+
scope: "openid profile User.Read",
49+
},
50+
},
51+
async profile(profile, tokens) {
4252
const email = profile.email || profile.preferred_username || "";
53+
const image = await fetchProfilePicture(`https://graph.microsoft.com/v1.0/me/photos/48x48/$value`, tokens.access_token);
4354
const newProfile = {
4455
...profile,
4556
email,
46-
// throws error without this - unsure of the root cause (https://stackoverflow.com/questions/76244244/profile-id-is-missing-in-google-oauth-profile-response-nextauth)
4757
id: profile.sub,
4858
isAdmin:
4959
adminEmails?.includes(profile.email?.toLowerCase()) ||
5060
adminEmails?.includes(profile.preferred_username?.toLowerCase()),
61+
image: image,
5162
};
63+
console.log("Azure AD profile:", newProfile);
5264
return newProfile;
5365
},
5466
})
@@ -94,6 +106,30 @@ const configureIdentityProvider = () => {
94106
return providers;
95107
};
96108

109+
export const fetchProfilePicture = async (profilePictureUrl: string, accessToken: any): Promise<any> => {
110+
console.log("Fetching profile picture...");
111+
var image = null
112+
const profilePicture = await fetch(
113+
profilePictureUrl,
114+
accessToken && {
115+
headers: {
116+
Authorization: `Bearer ${accessToken}`,
117+
},
118+
}
119+
);
120+
if (profilePicture.ok) {
121+
console.log("Profile picture fetched successfully.");
122+
const pictureBuffer = await profilePicture.arrayBuffer();
123+
const pictureBase64 = Buffer.from(pictureBuffer).toString("base64");
124+
image = `data:image/jpeg;base64,${pictureBase64}`;
125+
}
126+
else {
127+
console.error("Failed to fetch profile picture:", profilePictureUrl, profilePicture.statusText);
128+
}
129+
return image;
130+
};
131+
132+
97133
export const options: NextAuthOptions = {
98134
secret: process.env.NEXTAUTH_SECRET,
99135
providers: [...configureIdentityProvider()],

0 commit comments

Comments
 (0)