expo-auth-session exchangeCodeAsync only returns accessToken, not idToken or refreshToken with azure

105 Views Asked by At

We are using azure as our main authentication service. After logging in to microsoft, I can see the accessToken is coming back as a jwt token with a payload utilizing the function exchangeCodeAsync(...).

The problem is the function exchangeCodeAsync(...) only returns the accessToken, and not the idToken and refreshToken(which values come back as undefined).

Is there something I'm missing in the parameters of exchangeCodeAsync(...) that needs to be added/changed?

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"
    }
  }
}

The Results

enter image description here

1

There are 1 best solutions below

0
On BEST ANSWER

So, all I needed to do is add these values in the scope...

scopes: ['https://www.example.com/API.All', 'openid', 'profile', 'offline_access']

Note: I tried just adding in profile, and it errored out. All 3 additional values were required.