Expo-auth-session exchangeCodeAsync对接Azure仅返回accessToken问题咨询
问题描述
我们使用Azure作为主要认证服务,通过Microsoft登录后,调用exchangeCodeAsync函数可获取到带载荷的JWT格式accessToken,但该函数仅返回accessToken,idToken和refreshToken均为undefined。请问是否需要添加或修改exchangeCodeAsync的参数?
App.tsx
import * as React from 'react'; import * as WebBrowser from 'expo-web-browser'; import { exchangeCodeAsync, fetchUserInfoAsync, makeRedirectUri, Prompt, useAuthRequest, useAutoDiscovery, } from 'expo-auth-session'; import { Button, Text, SafeAreaView, Platform } from 'react-native'; WebBrowser.maybeCompleteAuthSession(); const clientId = '<my_client_id>'; const redirectUri = makeRedirectUri({ path: Platform.select({ android: 'com.example/<my_decrypted_hash_value>', ios: 'com.example://auth', default: undefined }) }); export default function App() { // Endpoint const discovery = useAutoDiscovery('https://login.microsoftonline.com/<my_tenant_id>/v2.0'); // Request const [request, , promptAsync] = useAuthRequest( { prompt: Prompt.Login, clientId, scopes: ['https://www.example.com/API.All'], redirectUri, }, discovery, ); // functions const login = async () => { try { const propmtResponse = await promptAsync(); if (request && propmtResponse?.type === 'success' && discovery) { const responseExchangeCode = await exchangeCodeAsync( { clientId, code: propmtResponse.params.code, extraParams: request.codeVerifier ? { code_verifier: request.codeVerifier } : undefined, redirectUri, }, discovery, ); console.log('responseExchangeCode:', responseExchangeCode); // <---------- has access token only } else { throw new Error('something went wrong'); } } catch(error: any) { console.log('error:', error); } }; return ( <SafeAreaView> <Button disabled={!request} title="Login" onPress={login} /> </SafeAreaView> ); }
app.json
{ "expo": { "name": "My App", "slug": "My-App", "version": "1.0.0", "scheme": "msauth", "orientation": "portrait", "icon": "./assets/icon.png", "userInterfaceStyle": "light", "splash": { "image": "./assets/splash.png", "resizeMode": "contain", "backgroundColor": "#ffffff" }, "assetBundlePatterns": [ "**/*" ], "ios": { "supportsTablet": true, "bundleIdentifier": "com.example", "buildNumber": "1.0.0" }, "android": { "adaptiveIcon": { "foregroundImage": "./assets/adaptive-icon.png", "backgroundColor": "#ffffff" }, "package": "com.example", "versionCode": 1 }, "web": { "favicon": "./assets/favicon.png" } } }
返回结果

解决方案
要拿到idToken和refreshToken,需要做以下调整:
补充授权请求的scopes
Azure AD v2.0要求必须声明对应范围才能返回idToken和refreshToken:openid+profile:用于获取idToken(包含用户身份信息)offline_access:用于获取refreshToken(用于静默刷新accessToken)
修改useAuthRequest的scopes配置:
const [request, , promptAsync] = useAuthRequest( { prompt: Prompt.Login, clientId, scopes: ['openid', 'profile', 'offline_access', 'https://www.example.com/API.All'], redirectUri, }, discovery, );验证Azure AD应用配置
确保Azure AD应用注册的认证设置中:- 已启用"ID令牌"(在"高级设置"的"令牌配置"里添加或确认)
- 允许发放"刷新令牌"(默认开启,但需确认未被禁用)
- 重定向URI和代码中
redirectUri完全匹配
调整后,调用exchangeCodeAsync就能同时获取到accessToken、idToken和refreshToken了。
内容的提问来源于stack exchange,提问作者Fiddle Freak
相关产品推荐
相关产品推荐

