Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Handling User Auth for a SPA App on Azure

Handling User Auth for a SPA App on Azure

Stream description:
Many modern web applications use a SPA architecture: a single-page web app for the frontend and an API for the backend. In this talk, we'll discover how you can add user authentication to a SPA app using Microsoft Entra, using the MSAL.JS SDK on the frontend and the MSAL Python SDK on the backend. Learn how to set up Entra applications correctly, one for the client and one for the server, and how to use the on-behalf-of-flow on the server for handling tokens sent from the client. Our example application will be an AI RAG application with a React frontend and Python backend, but you can apply the same principles to any SPA applications that need user authentication.

Stream:
https://www.youtube.com/watch?v=ymPC2KakuF8

Pamela Fox

July 10, 2024
Tweet

More Decks by Pamela Fox

Other Decks in Technology

Transcript

  1. Securing AI Apps on Azure Date Topic Speakers July 2

    5-6PM UTC Using Keyless Auth with Azure AI Services Marlene Mhangami Pamela Fox July 8 5-6PM UTC Add User Login to AI Apps using Built-in Auth James Casey Pamela Fox July 9 7-8PM UTC Add User Login to AI Apps using MSAL SDK Ray Luo Pamela Fox July 10 7-8PM UTC Handling User Auth for a SPA App on Azure Matt Gotteiner July 17 7-8PM UTC Data Access Control for AI RAG Apps on Azure Matt Gotteiner Pamela Fox July 25 11PM-12PM Deploying an AI App to a Private Network on Azure Matt Gotteiner Anthony Shaw https://aka.ms/S-1355
  2. Securing AI Apps on Azure: Handling User Auth for a

    SPA App on Azure Matthew Gotteiner, Azure AI Search aka.ms/securing-spa-slides
  3. What is a Single Page Application (SPA)? • Simple to

    create • Great for read-only experiences • Every page has a separate URL by default • Doesn't necessarily require Javascript Traditional Web Application Single Page Application • More setup is required • Rich and customizable user interface • The application backend exposes an API • Requires Javascript to call API
  4. How do Authentication and Authorization Work? Authenticate users through the

    Open ID Connect protocol (OIDC) Authorize users using OAuth 2.0 protocol Terminology: Auth Flow ▪ Authentication / Authorization Exchange Authorization Server ▪ Issues tokens for apps to access protected resources Client ▪ App requesting access to a protected resource Token ▪ Allow a client to access a protected resource Resource Owner ▪ Owns protected resource client is trying to access Resource Server ▪ Provides access to protected data
  5. Token types Access token • Issued by an authorization server

    as part of an OAuth 2.0 flow. Can be used to access web APIs and other protected resources. ID Token • Issued as part of OpenID Connect flow. Used by the client to identify the user. Shouldn’t be used to access web APIs.
  6. Access Token • Commonly a JSON blob that contains claims

    about the subject • Resource API needs to validate these claims, make authorization decisions based on these claims and potentially other information • It is passed to the API inside request headers "Accept": "application/json, text/plain, */*​ " "Accept-Encoding": "gzip,deflate,sdch​ " "Accept-Language": "en-GB, en;g=0,8,en- US;0=6,de;g=0,4​ " "Authorization": "bearer EyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1hiIsImtpZ CI6InU0T2ZORlBId0VCb3NIanRy...​ " "Cache-Control": "no-cache​ " "Connection": "keep-alive​ " "Host": "localhost:8080"​ "..." Request Headers
  7. Access Token Claims "aud": "416684a7-0b52-4fa3-9918-e76d16542be2", "iss": "https://login.microsoftonline.com/c72a295d-d7a5-41ea-a351-b15dd9f67215/v2.0", "iat": 1563883336, "nbf":

    1563883336, "exp": 1563887236, "azp": "bb764c21-49b8-49de-aa24-6c76d7dc800f", "oid": "0e748cd0-5d2a-4918-a351-9549e75fd1dd", "scp": "Catalog.View.Published", "roles": "Catalog.View", "wids": "9c6df0f2-1e7c-4dc3-b195-66dfbd24aa8f", "sub": "0X7PvET4orHRnRYndMvA4CYlYxg_CowsE1BGTIAK6hE", "tid": "c72a295d-d7a5-41ea-a351-b15dd9f67215", "preferred_username": [email protected], "email": [email protected]", "name": "Jane Bowen", Key: Authentication: know the subject Authorization: should subject have access Display-only https://learn.microsoft.com/entra/identity-platform/access-token-claims-reference
  8. What kinds of clients are there? Confidential Client Application Clients

    capable of maintaining the confidentiality of their credentials (e.g., client implemented/deployed on a secure server with restricted access to the client credentials) Public Client Application Clients incapable of maintaining the confidentiality of their credentials. e.g., clients executing on the device used by the resource owner, such as an installed native application (desktop apps, mobile apps) or a web browser-based application (SPA), and even apps that run on devices without a browser. Note: • Both confidential and public clients can sign in users and/or acquire access tokens.
  9. SPA Frontend Entra SPA Application SPA Backend Entra Backend Application

    Azure OpenAI Azure AI Search Architecture for SPA App with user authentication
  10. Registering with the Microsoft identity platform To request tokens from

    the Microsoft identity platform, you need to register a Microsoft Entra application and create a service principal for it. Microsoft Entra Application Object Microsoft Graph Service Principal Microsoft identity platform
  11. Registering Client Entra application with Graph SDK graph_client = GraphServiceClient(credentials=credential,

    scopes=scopes) graph_client.applications.post(Application( display_name=f"Azure Search OpenAI Client App {identifier}", sign_in_audience="AzureADMyOrg", web=WebApplication( redirect_uris=["http://localhost:50505/.auth/login/aad/callback"], implicit_grant_settings=ImplicitGrantSettings(enable_id_token_issuance=True)), spa=SpaApplication(redirect_uris=["http://localhost:50505/redirect", "http://localhost:5173/redirect"]), required_resource_access=[ RequiredResourceAccess( resource_app_id=server_app_id, resource_access=[ ResourceAccess(id=server_app.api.oauth2_permission_scopes[0].id, type="Scope])]), RequiredResourceAccess( resource_app_id="00000003-0000-0000-c000-000000000000", resource_access=[ ResourceAccess(id="e1fe6dd8-ba31-4d61-89e7-88639da4683d", type="Scope") # Graph User.Read ])])) The client application requires access to the server application auth_init.py
  12. Registering Server Entra application with Graph SDK graph_client = GraphServiceClient(credentials=credential,

    scopes=scopes) graph_client.applications.post(Application( api=ApiApplication( oauth2_permission_scopes=[PermissionScope( id="7b207263-0c4a-4127-a6fe-38ea8c8cd1a7", user_consent_display_name="Access Azure Search OpenAI Chat API", user_consent_description="Allow the app to access Azure Search OpenAI Chat API on your behalf", value="access_as_user", type="User")]), required_resource_access=[RequiredResourceAccess( resource_app_id="00000003-0000-0000-c000-000000000000", resource_access=[ ResourceAccess(id="e1fe6dd8-ba31-4d61-89e7-88639da4683d", type="Scope"), # Graph User.Read ])], identifier_uris=[f"api://{server_app_id}"])) The server application defines its own permission scopes: auth_init.py
  13. Setting Entra application credentials with Graph SDK request_password = AddPasswordPostRequestBody(

    password_credential=PasswordCredential(display_name="WebAppSecret"), ) graph_client.applications.by_application_id(app_id) .add_password.post(request_password) Currently, app registrations can use either password or certificate credentials. In the future, they can use a managed identity as a federated identity credential! auth_init.py
  14. Implementing the authentication flow Option 1: For auth on Azure

    App Service or Container Apps Option 2: For auth on any host (including local) Use MSAL packages to orchestrate OIDC flow using app registration Configure built-in authentication and authorization with Microsoft identity platform as the provider
  15. OAuth2 authentication flow with OIDC App backend Microsoft Entra servers

    Browser OAuth2 Leg 1 Initiate the authorization code flow User Signs in Returns redirect to redirectURI OAuth2 Leg 2 Exchange authorization code for token Returns redirect to URI Visits webapp Returns access token Return authorized results and ID token User has not signed in
  16. Using MSAL.JS Create a public client application and initialize it

    with your client ID. Then call the correct methods to either fetch a cached token or acquire one using an interactive flow. const msalConfig = { auth: { clientId: "your_client_id", redirectUri: "https://contoso.com" } }; const msalInstance = new PublicClientApplication(msalConfig); await msalInstance.initialize(); msalInstance.acquireTokenSilent({ scopes: ["User.Read"] }) .then(tokenResponse => { ... }) .catch(async (error) => { if (error instanceof InteractionRequiredAuthError) { return msalInstance.acquireTokenPopup(request); } ... LEG 1 LEG 2
  17. Using the Python MSAL SDK for authentication flows app =

    msal.ConfidentialClientApplication( os.getenv("CLIENT_ID"), client_credential=os.getenv("CLIENT_SECRET"), authority=f"https://login.microsoftonline.com/{os.getenv('TENANT_ID')}", ) flow = app.initiate_auth_code_flow(scopes, redirect_uri=redirect_uri) # Redirect the user to the URI returned by that function ^ ... result = app.acquire_token_by_auth_code_flow(auth_flow, auth_response) access_token = result["access_token"] Configure the client ID and client credentials according to what your provisioned, then call the correct methods to generate the correct authentication URI and exchange the authorization code for a token. LEG 1 LEG 2
  18. Configuration of Cross-Origin Resource Sharing (CORS) Both the App Services

    instance and the Quart app need to have the correct CORS settings to support alternative frontends. // Bicep Template resource appService 'Microsoft.Web/sites@2022-03-01' = { properties: { siteConfig: { cors: { allowedOrigins: [ 'https://www.contoso.com' ] } } } ... # Python app = Quart("app") cors(app, allow_origin=["https://www.contoso.com"], allow_methods=["GET", "POST"])
  19. Try our samples and learn more! Azure OpenAI + AI

    Search + Entra + MSAL + App Service Built-in Auth aka.ms/ragchat Find more samples at: aka.ms/azai Java JavaScript Python .NET OpenAI Assistants Fine-tuning ...and more! Access Control in Generative AI applications with Azure AI Search aka.ms/rag-access-control Microsoft Entra developer center aka.ms/dev/ms-entra
  20. Securing AI Apps on Azure Date Topic Speakers July 2

    5-6PM UTC Using Keyless Auth with Azure AI Services Marlene Mhangami Pamela Fox July 8 5-6PM UTC Add User Login to AI Apps using Built-in Auth James Casey Pamela Fox July 9 7-8PM UTC Add User Login to AI Apps using MSAL SDK Ray Luo Pamela Fox July 10 7-8PM UTC Handling User Auth for a SPA App on Azure Matt Gotteiner July 17 7-8PM UTC Data Access Control for AI RAG Apps on Azure Matt Gotteiner Pamela Fox July 25 11PM-12PM Deploying an AI App to a Private Network on Azure Matt Gotteiner Anthony Shaw https://aka.ms/S-1355