Ionic Angular应用集成Auth0与Azure身份提供者的API鉴权调用方案
核心逻辑前提:你需要在Auth0社交登录配置阶段打通Microsoft身份提供者的权限链路,让Auth0在用户完成认证后,能返回Microsoft原生签发、可直接访问Azure App Service API的access token,而非仅返回Auth0自身生成的token——这是90%的开发者会踩的核心坑。
1. 前置平台配置
先把Auth0和Azure AD两边的权限打通,否则后续拿不到合法的访问token:
- 在Auth0后台配置Microsoft社交身份连接时,除基础的openid、profile、email权限外,额外在「Permissions」配置项中添加你Azure API暴露的权限范围(即你在Azure AD中给App Service对应API注册的scope,格式通常为
api://<你的Azure API客户端ID>/user_impersonation) - 在Auth0的Application配置页,按Ionic移动端规则配置回调、登出地址,使用自定义scheme即可,例如
com.your-app-name://callback - 进入Azure AD管理页确认:App Service对应的API注册已开启id_token、access_token签发权限,允许Auth0作为客户端请求对应scope的token,否则Auth0无法换取到微软原生的access token
- 若你给Azure App Service开启了Easy Auth(App Service内置身份认证),需在配置中添加合法token audience,包含你API对应的客户端ID,避免后续请求报401
2. Ionic Angular端Auth0基础集成
首先安装Auth0官方Angular SDK:
npm install @auth0/auth0-angular
在app.module.ts中初始化Auth0模块,关键是把Azure API对应的scope加入授权参数,否则Auth0不会主动向微软请求对应API的访问权限:
// app.module.ts 核心配置片段 import { AuthModule } from '@auth0/auth0-angular'; @NgModule({ imports: [ AuthModule.forRoot({ domain: '你的Auth0租户域名', clientId: '你的Auth0 Application客户端ID', authorizationParams: { redirect_uri: 'com.your-app-name://callback', // 必须加入Azure API对应的scope,否则拿不到合法访问token scope: 'openid profile email offline_access api://<你的Azure API客户端ID>/user_impersonation' }, useRefreshTokens: true, // 移动端开启token刷新,避免频繁触发登录 cacheLocation: 'localstorage' // 移动端使用localstorage缓存token,避免切后台后内存缓存丢失 }) ] })
在登录组件中直接调用SDK方法触发认证即可:
import { AuthService } from '@auth0/auth0-angular'; constructor(private auth: AuthService) {} // 触发登录 handleLogin() { this.auth.loginWithRedirect(); }
3. 获取微软签发的access token
不要直接使用Auth0返回的id_token或Auth0自身签发的access token请求Azure API,Azure侧仅认可微软身份平台签发的token。
通过Auth0 SDK的getAccessTokenSilently方法,传入Azure API对应的audience和scope,即可拿到合法的微软原生access token:
// 封装获取Azure访问token的方法 getAzureApiToken(): Observable<string> { return this.auth.getAccessTokenSilently({ authorizationParams: { audience: 'api://<你的Azure API客户端ID>', scope: 'api://<你的Azure API客户端ID>/user_impersonation' } }); }
校验token是否正确的方法:把拿到的token做JWT解析,确认
iss字段值为微软身份端点(格式为https://login.microsoftonline.com/<你的Azure租户ID>/v2.0),如果iss为Auth0域名,说明scope或audience配置错误,拿到的是无效token。
4. 封装HTTP拦截器自动传递token
Angular场景下最优实践是编写全局HTTP拦截器,所有发往Azure App Service域名的请求自动注入Authorization头,无需每个接口单独处理:
首先生成拦截器文件:
ionic g interceptor auth-token
编写拦截器逻辑:
// auth-token.interceptor.ts import { Injectable } from '@angular/core'; import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor } from '@angular/common/http'; import { AuthService } from '@auth0/auth0-angular'; import { Observable, switchMap } from 'rxjs'; @Injectable() export class AuthTokenInterceptor implements HttpInterceptor { constructor(private auth: AuthService) {} intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> { const azureApiDomain = 'https://<你的Azure App Service域名>.azurewebsites.net'; // 仅拦截发往Azure API的请求,避免给第三方请求泄露token if (!request.url.startsWith(azureApiDomain)) { return next.handle(request); } return this.auth.getAccessTokenSilently({ authorizationParams: { audience: 'api://<你的Azure API客户端ID>', scope: 'api://<你的Azure API客户端ID>/user_impersonation' } }).pipe( switchMap(token => { // 克隆请求并添加Authorization头,格式固定为Bearer <token> const authedRequest = request.clone({ setHeaders: { Authorization: `Bearer ${token}` } }); return next.handle(authedRequest); }) ); } }
在app.module.ts的providers数组中注册拦截器使其生效:
providers: [ { provide: HTTP_INTERCEPTORS, useClass: AuthTokenInterceptor, multi: true } ]
5. 发起API调用
拦截器配置完成后,直接使用Angular原生HttpClient发起请求即可,拦截器会自动完成token获取、请求头注入的全流程:
import { HttpClient } from '@angular/common/http'; constructor(private http: HttpClient) {} // 示例:请求Azure App Service上的用户信息接口 fetchUserInfo() { return this.http.get('https://<你的Azure App Service域名>.azurewebsites.net/api/user/profile'); }
常见问题排查
- 如果请求返回401,先解析请求头里携带的token,确认签发者为微软身份平台、aud字段包含你的Azure API客户端ID、scope字段包含你配置的API权限
- 移动端登录完成后无法跳回APP,需检查
capacitor.config.ts中是否配置了和Auth0后台一致的自定义url scheme - 静默获取token失败时,需捕获错误并主动触发
loginWithRedirect重新走认证流程,避免接口持续报错
内容的提问来源于stack exchange,提问作者user1005310

