3

I'm by no means an expert on MSAL/JWT/Graph authentication, but I'm hoping someone can explain this issue more clearly to me, or help me understand if there's a workaround or better approach.

Essentially, there are certain scenarios where I might end up with a Microsoft Graph JWT token. Two examples I can think of easily are using the Microsoft Graph Toolkit or using Tabs SSO in Microsoft Teams. In both cases, I can get relevant identity information for the user from the JWT token I would have already (via Graph Toolkit or via Teams SSO) - their Azure AD Object Id and their Tenant Id. However, I can't use that same token to my own backend API, because, from my research, I can't perform basic token verification against that JWT token. I'd like to be able, for example, to store information against that user and tenant Id combination.

I do understand that I can do my own authentication (e.g. MSAL.js), and I can even use the SAME Azure AD Application by extending its use, but it would be much easier to simply use the token I have access to already, if there was just a way to validate it. In Teams, as an example, the SSO user experience is nicely integrated, but I'd need to put the user through ANOTHER signin, potentially even for the SAME Azure AD Application. [Update: so technically it's not another 'sign-in' - the user is signed in already, hence 'SSO', but they need to consent again, in this case against the very same app they consented to a moment before].

So, my question is, is there any way to safely verify the existing token?

Hilton Giesenow
  • 9,809
  • 2
  • 10
  • 24

2 Answers2

4

An AAD token for the Graph is not meant for your app/services and you should not be attempting to validate or even decode it. In some cases, the token could be encrypted thus preventing you from even cracking it open. The only thing you can safely do with a Graph token is call a Graph API with it (as long as the token has the necessary scopes). If the token doesn't have the necessary scopes then you will get an error back from the Graph.

Can you help me understand your scenario better? How are you generating this Graph token? In general, when you use Tab SSO the token generated by Teams is not for the Graph; it's for your Web API that you registered with AAD and listed in your app manifest's webApplicationInfo section. To call downstream Graph APIs you would need to exchange this token via AAD's OBO flow: https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-on-behalf-of-flow

If your app doesn't have the necessary consent then this exchange will fail which you can use as a signal to trigger a popup authentication flow and get the user's consent. This is documented here: https://learn.microsoft.com/en-us/microsoftteams/platform/tabs/how-to/authentication/auth-aad-sso

Yuri Dogandjiev
  • 178
  • 1
  • 8
  • Thank Yuri, I appreciate the time on this. Here's my scenario - basically, I *have* a backend API, and I want to store information for the user, and for the tenant overall. I don't even really need authorization in some of my apps, because it's personal info just for that user. However, I _do_ need authentication, to prove that the caller is that specific user, from that specific tenant. Obviously, if there was nothing in place (e.g. a standalone SPA), I would implement an end-to-end scenario (e.g. using MSAL). – Hilton Giesenow Dec 15 '20 at 06:37
  • (part 2 - ran out of space) However, Teams SSO provides a more seamless experience for the user, and it gives back a basic identify token, already containing everything I need (user id and tenant id), but my research tells me that I can't validate, and therefor can't use, this existing token. In theory, I don't really need an 'OBO' because I'm not trying to call services in the Graph - I just want to use the identify information that the token -already- contains. – Hilton Giesenow Dec 15 '20 at 06:37
  • Hey Hilton, thank you for helping me understand your scenario better. Can you please confirm that you're acquiring an access token using the `microsoftTeams.authentication.getAuthToken` API? If so, have you tried putting that token into https://jwt.ms and inspecting its contents? This token should have your Web API's resourceUri as the audience which means it's meant for your service. You can validate it using something like Passport.js w/ the passport-azure-ad strategy. You can see how I do that in my sample app here: https://github.com/ydogandjiev/taskmeow/blob/master/server/auth-service.js – Yuri Dogandjiev Dec 16 '20 at 07:41
  • 1
    Yup, that's where I'm getting it from, and I have inspected it with jwt.io . I think I've realised my issue though - I was struggling to understand how to verify a multi-tenant token as I wasn't seeing what I expected to see. As I understand it now - I can verify that (A) *Microsoft* signed it (OIDC signing keys from "https://login.microsoftonline.com/organizations/v2.0/.well-known/openid-configuration" and that it (B) belongs to MY application (using the audience), which is I all I need, I guess. – Hilton Giesenow Dec 16 '20 at 15:24
  • 1
    Based on that, I can trust the claims, in particular oid and tid that I need. – Hilton Giesenow Dec 16 '20 at 15:27
  • Thanks for the help on this! – Hilton Giesenow Dec 16 '20 at 15:27
0

To validate the access tokens, you need to validate the signature, claims, issuer, the audience, and the signing tokens, these need to be validated against the values in the OpenID discovery document.

Reference - https://learn.microsoft.com/en-us/azure/active-directory/develop/access-tokens#validating-tokens

Sample for C# - How to validate Azure AD security token?

Joy Wang
  • 39,905
  • 3
  • 30
  • 54
  • 1
    The problem in this case is that it's not just an 'Azure AD' token, it's also a Graph token specifically, which doesn't seem to be able to pass validation in the ordinary way - that's basically the point I'm making. – Hilton Giesenow Nov 24 '20 at 05:31