Search code examples
react-nativeoauth-2.0azure-active-directoryjwtexpo

Getting user data through an Azure AD OAuth login - React Native Expo App


In my app, I authenticate users through an Microsoft Azure AD Login using useAuthRequest, as the Expo Documentation suggests (This login method is working successfully). Inside my request, I parse in the scopes ['openid', 'profile', 'email'].

I want to display data such as the users name and email inside my application, but don’t know how to get that data.

After some research, I discovered that this data is kept inside a Token in a JWT format, and it is possible to decode it using a simple JWT decoder package.

The problem is that I don't know how or where to get that specific Token to decode it.

Here is an extraction from my code:

const discovery = useAutoDiscovery(`${config.ENDPOINT_URL}`);

    const [request, response, promptAsync] = useAuthRequest(
      {
        clientId: `${config.CLIENT_ID}`,
        clientSecret: `${config.CLIENT_SECRET}`,
        scopes: [ 'openid', 'profile', 'email'],
        prompt: 'login',
        redirectUri: "msauth.*MyBundleId*://auth",
        returnUrl: "msauth.*MyBundleId*://auth",
      },
        discovery,
        console.log(discovery)
      );

The console.log(discovery) returns two specific links that I think are worth mentioning:

"token_endpoint": "https://login.microsoftonline.com/*MyAppsTenantId*/oauth2/v2.0/token",

and:

"userinfo_endpoint": "https://graph.microsoft.com/oidc/userinfo"

When entering the token_endpoint on my browser, it shows an Error message saying

AADSTS900561: The endpoint only accepts POST, OPTIONS requests. Received a GET request.

and when entering the userinfo_endpoint link on my browser, it returns a hash with the following data:

{"error":{"code":"InvalidAuthenticationToken","message":"Access token is empty.","innerError":{"date":"2022-04-28T13:00:07","request-id":"*MyAppTenantId","client-request-id":"*ClientRequestId*"}}}

Useful links:

-Microsoft UserInfo

-OpenID Scopes

-Active Directory Protocols

If you have any clue, tip, or information on how to get the JWT token containing the user data, please share below and I will be very happy to read it and comment on.


Solution

  • I finally solved this issue!

    I found a library called azure-ad-graph-expo which does exactly what I wanted to do in a very simple way -> No need for API callings and parsing access tokens.

    Here is an extraction from my code:

      const [resultData, setResultData] = useState({});
    
      const _handlePressAsync = async () => {
        let result = await openAuthSession(azureAdAppProps);
        setResultData({ result });
      }
    
      const azureAdAppProps = {
        clientId        :   `******************`,
        tenantId        :   `******************`,
        scope           :   'user.read',
        redirectUrl     :   AuthSession.makeRedirectUri({ path: "auth"}),
        returnUrl       :   "mybundleid://auth",
        clientSecret    :   `******************`,
        domainHint      :   'login.microsoftonline.com',
        prompt          :   'login'
    };
    

    You must set your redirect Url in the Azure portal.

    This code worked successfully because it was tested in the app build itself instead of the Expo Go App:

    • => To create a build, run expo build:ios or expo build:android

    • => If you want to test it in the Expo Go app, set your localhost as a redirectUrl on the Azure AD portal and set the code as redirectUrl: AuthSession.makeRedirectUri()

    • => For the bundle id, you can set your own -> inside app.json create the "scheme" inside the "expo:" bracket. Bundle IDs are written as in the following pattern: com.your-company.app-name.

    To test if my app was getting the user data, the following code was added right below the login button:

            {resultData ? (
              <Text>{JSON.stringify(resultData)}</Text>
            ) : 
              <Text>Nothing to see here.</Text>}
    

    And here is the result, right after authenticating: User Data

    If you have any question or addition to this issue feel free to comment below! :D and thanks very much for all the help and comments in this thread!