9

I just wanted to know how can we validate the azure ad access token in a backend API in my case i.e. Django rest framework.

Consider that I have a single page app or a native app and a backend API (django rest framework) completely independen of each other. In my case if my single page app/native app wants to access certain data from the backend API, and inorder to access the API, user should be logged in the backend API.

So what my approch is to make use of MSAL library to get the access token from the SPA/native app and then once token is acquired, pass that token to backend API, validate it, get the user info from graph api. If user exists in the DB then login the user and pass the required info. If user info doesn't exist then create the user, login and pass the info from the API.

So my question is when I pass the access token to my backend api, how can I validate that the token that a user/SPA/native app has passed to backend API is valid token or not?

Is it just we need to make an API call to graph API endpoint with accessToken that user/SPA/native passed and if it is able to get the user data with the accessToken then then token is valid or if it fails then the accessToken is invalid.

Is it the general way to validate the token or some better approach is there? Please help

Aashay Amballi
  • 1,321
  • 3
  • 17
  • 39
  • This might help: https://learn.microsoft.com/en-us/azure/databricks/dev-tools/api/latest/aad/troubleshoot-aad-token#validate-an-access-token What it did was decoded the token and validated the **aud** and **iss** key values against my azure AD configurations. Refer to [this](https://learn.microsoft.com/en-us/azure/active-directory/develop/access-tokens) for further details on claims that can be validated. – sachith95 Oct 14 '21 at 04:23
  • Hi @aashay, have found any solution – Chandhan Narayanareddy Apr 26 '22 at 16:35
  • 1
    hey @ChandhanNarayanareddy, I have not found any solution... I had this requirement last year when I was working on the project and since I'm not part of that project anymore I didn't try or look for any solutions. – Aashay Amballi Apr 26 '22 at 18:32

3 Answers3

0

Good day sir, I wanna share some of my ideas here and I know it's not a solution but it's too long for a comment.

I created a SPA before which used msal.js to make users sign in and generate access token to call graph api, you must know here that when you generate the access token you need to set the scope of the target api, for example, you wanna call 'graph.microsoft.com/v1.0/me', you need a token with the scope 'User.Read, User.ReadWrite' and you also need to add delegated api permission to the azure app.

So as the custom api of your own backend program. I created a springboot api which will return 'hello world' if I call 'localhost:8080/hello', if I wanna my api protected by azure ad, I need to add a filter to validate all the request if has a valid access token. So I need to find a jwt library to decode the token in request head and check if it has a token, if the token has expired and whether the token has the correct scope. So here, which scope is the correct scope? It's decided by the api you exposed in azure ad. You can set the scope named like 'AA_Custom_Impression', and then you can add this delegate api permission to the client azure ad app, then you that app to generate an access token with the scope of 'AA_Custom_Impression'. After appending the Bearer token in calling request, it will be filtered by backend code.

I don't know about python, so I can just recommend you this sample, you may try it, it's provided by microsoft.

Tiny Wang
  • 10,423
  • 1
  • 11
  • 29
  • Hello Tiny-wa. Thanks for your reply. I guess my question was not explaining everything. I don't want my backend API (Django Rest Framework) protected by azure AD, because it will have its own custom authorization. Basically I what I wanna do is kind of a registration process you can say. When a user logs in through the SPA/native app msal.js will generate an access token and that access token will be passed to the backend API in order to check whether that user is authorized to access a certain endpoint or not. So when user does this for the first time user record will not be there in the DB. – Aashay Amballi Mar 21 '21 at 07:57
  • So what I wanna do is. If the user record is not there then with the access token that native/SPA has passed Backend API will make a graph API call for ex: 'graph.microsoft.com/v1.0/me'. With that backend API will get user info, it will create the user record, logs in the created user, and return the user with the JWT token that is generated by Backend API. so now native/SPA will receive that JWT token and it will make a call to the Backend API with that JWT token that is provided by Backend API. for example 'localhost:8080/' – Aashay Amballi Mar 21 '21 at 08:07
  • So now Backend API will know that the JWT token (which is generated by Backend API) is valid and it will return the appropriate data. in our example it would return hello. So my question was since we are passing the Graph API access token to the Backend API. What is the best way to validate it? – Aashay Amballi Mar 21 '21 at 08:20
  • Yes sir, thanks for your response and I think I can get you. So first, I think I need to tell you that the jwt token(we said access token above) could be decoded to a json object, the json object contains much cliams, you can [refer to this doc](https://learn.microsoft.com/en-us/azure/active-directory/develop/access-tokens#payload-claims) to know the details and make sure how could you judge if the token is valid. At last, I think your problem can convert to find a [decode library](https://stackoverflow.com/questions/38340078/how-to-decode-jwt-token) to decrypt the token instead. – Tiny Wang Mar 21 '21 at 13:52
0

I've solved the similar issue. I don't found how to directly validate access token, but you can just call graph API on backend with token you've got on client side with MSAL.

Node.js example:

class Microsoft {

  get baseUrl() {
    return 'https://graph.microsoft.com/v1.0'
  }

  async getUserProfile(accessToken) {
    const response = await got(`${this.baseUrl}/me`, {
      headers: {
        'x-li-format': 'json',
        Authorization: `Bearer ${accessToken}`,
      },
      json: true,
    })
    return response.body
  }
  
  // `acessToken` - passed from client
  async authorize(accessToken) {
    try {
      const userProfile = await this.getUserProfile(accessToken)
      const email = userProfile.userPrincipalName

      // Note: not every MS account has email, so additional validation may be required
      const user = await db.users.findOne({ email })

      if (user) {
        // login logic
      } else {
        // create user logic
      }
    } catch (error) {
      // If request to graph API fails we know that token wrong or not enough permissions. `error` object may be additionally parsed to get relevant error message. See https://learn.microsoft.com/en-us/graph/errors 
      throw new Error('401 (Unauthorized)')
    }
  }
}
Kuzzy
  • 562
  • 1
  • 9
  • 24
0

Yes we can validate the Azure AD Bearer token.

You can fellow up below link,

https://github.com/odwyersoftware/azure-ad-verify-token https://pypi.org/project/azure-ad-verify-token/

We can use this for both Django and flask.

You can directly install using pip but I'm not sure in Django. If Django install working failed then try to copy paste the code from GitHub

Validation steps this library makes:
    1. Accepts an Azure AD B2C JWT.
         Bearer token
    2. Extracts `kid` from unverified headers.
         kid from **Bearer token**
    3. Finds `kid` within Azure JWKS.
         KID from list of kid from this link `https://login.microsoftonline.com/{tenantid}/discovery/v2.0/keys`
    4. Obtains RSA key from JWK.

    5. Calls `jwt.decode` with necessary parameters, which inturn validates:
    
        - Signature
        - Expiration
        - Audience
        - Issuer
        - Key
        - Algorithm
Eric Aya
  • 69,473
  • 35
  • 181
  • 253