I need a solution for accessing Microsoft graph api with a token which never expires for a multitenant application.
I am using frontend as react and backend as lambda function.
Actual requirement
Need to connect Microsoft app (which will give access to graph api's) with project where same auth will be used by multiple users, same authentication should work until it revoked.
Take OAuth 2.0 auth code grant as an example.
Currently, access token lifetime cannot be configured to be permanent.
Therefore,You can Request an access token
and you can Refresh the access token when it expired.
Related
I am using Azure AD access token instead of default openID connect server (keycloak) to protect the backend REST API. Could you please let me know if i need to make any changes for AuidenceValidator class under package security.oauth2.
Application flow:
UI(React JS) will access the Spring boot API by passing access token.
Please take a look at the ms-identity-java-webapi sample. The msal-obo-sample shows how to validate an access token acquired by MSAL using Spring Security. You will be interested specifically in AADClaimsVerifier and SecurityResourceServerConfig
I have set up an Azure Active Directory tenant with direct federation to Google. Next to that I have a .NET core web application using the OIDC code flow for getting both id_tokens and access and refresh tokens. The access token is used to call my API which is working fine.
Now the problem is whenever I use my refresh_token to get a new access_token I receive a new access_token, but no refresh_token. So I can only refresh once.
I only have this issue when authenticating with my Google account using direct federation. When I authenticate using a tenant native account I can refresh unlimited.
We have two multitenant Azure AD app registrations as described here. One for our single page application and one for our API. In our single page application backend we use the OpenIdConnect middleware to authenticate against Azure AD. Note that we are not using the common endpoint, but the tenant specific endpoint because otherwise direct federation does not work. We can reproduce this issue by intercepting the refresh token in the OnTokenResponseReceived event of the OIDC middleware and initiating the refresh flow as stated here (by using Postman for instance). The response is successful, but does only contain an access token, no refresh token.
Is this behavior by design?
I have a ReactJs frontend making requests to an API. Both hosted in Azure with app registrations in AAD as well.
I used to be able to use v1.0 auth endpoint, and create a valid token for the API:
https://login.microsoftonline.com/common/oauth2/authorize?client_id=<AAD_WEB_APP_ID>&resource=<AAD_API_ID>&response_type=token ...
If I understand the documentation correctly, this type of auth flow isn't allowed/possible in v2.0:
However, that Web API can receive tokens only from an application that has the same Application ID. You cannot access a Web API from a client that has a different Application ID. The client won't be able to request or obtain permissions to your Web API.
The reason for changing from v1.0 to v2.0 is that I need access to Microsoft Graph (Groups in particular).
My question is: How can I create an access_token that works for Microsoft Graph and my API? If that isn't possible, what would the correct auth flow be?
You don't need to switch to the v2 Endpoint for this, Microsoft Graph supports both v1 and v2 tokens (actually, every API I can think of that supports v2 also supports v1 but there might be an exception I'm forgetting).
The steps are pretty straightforward:
Update your AAD registration in the Azure Portal and add the Permissions for Microsoft Graph you're going to be using.
Instead of passing resource=<AAD_API_ID> in your URI, use resource=graph.microsoft.com. This will return a token that can be used with Microsoft Graph.
Important: You must request the Offline Access scope (offline_access) for this to work.
Where this gets confusing is that technically you cannot use the same Access Token to access both your API and Microsoft Graph. What is supported is switching the Resource when refreshing your token. So while, yes, you are using two different tokens, you're reusing the same credentials/authorization code.
Here is an example flow:
A user authenticates using your API as the Resource (resource=<AAD_API_ID>). This returns an Authorization Code back to your application.
The application posts the Authorization Code to the /token endpoint (also using your API as the Resource). This will return both an access_token and a refresh_token to the application.
Use this access_token to make calls into your API.
The application posts the refresh_token to the /token endpoint using graph.microsoft.com as the Resource. This will return a new access_token and refresh_token keyed to Microsoft Graph.
Use this new access_token to make calls into Microsoft Graph.
The application again posts the refresh_token to the /token endpoint but this time using your API as the Resource again. This will return a new access_token and refresh_token keyed to your API.
Call your API
You can repeat this cycle as needed. Depending on how often you need to switch, you can also keep access tokens for both your API and Graph in memory and reuse them until they expire. Just be sure and always store the last Refresh Token you received so you can fetch a refreshed token for either resource as needed.
On my initial analysis on the fetching the access token from Azure AD using OpenID connect protocol, I came to know that there are two ways to consider
Fetching access token using the signed in user's context where caching is used.
Fetching access token using application context.
Can anyone help me to know which needs to be consider with some example code.
Fetching access token using the signed in user's context where caching is used.
OpenID Connect implements authentication as an extension to the OAuth 2.0 authorization process. It provides information about the end user in the form of an id_token that verifies the identity of the user and provides basic profile information about the user.
Please refer to code sample :Calling a web API in a web app using Azure AD and OpenID Connect ,this sample uses the OpenID Connect ASP.Net OWIN middleware and ADAL .Net. In controller , you could get access token for specific resource using the signed in user's context :
string userObjectID = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value;
AuthenticationContext authContext = new AuthenticationContext(Startup.Authority, new NaiveSessionCache(userObjectID));
ClientCredential credential = new ClientCredential(clientId, appKey);
result = await authContext.AcquireTokenSilentAsync(todoListResourceId, credential, new UserIdentifier(userObjectID, UserIdentifierType.UniqueId));
Fetching access token using application context.
What do you mean by "application context" ? If you are talking about OAuth 2.0 Client Credentials Grant Flow , which permits a web service (confidential client) to use its own credentials instead of impersonating a user, to authenticate when calling another web service. You could refer to this scenario explanation and code samples .
To fetch an access token to the graph API, you need to:
redirect the user to the Azure authorization endpoint (https://login.microsoftonline.com/common/oauth2/v2.0/authorize),
to get back an authorization token,
that you need to provide Azure with, on the access token endpoint (https://login.microsoftonline.com/common/oauth2/v2.0/token), with your application credentials.
Finally, you can provide this access token to the userinfo endpoint on the graph API: https://graph.microsoft.com/v1.0/me
with some example code
I've written a sample code, but it depends totally on the language, environment and OIDC library you are using. In case you are using Java in a servlet environment with the MIT implementation of OIDC (MITREid Connect), my example to access the Microsoft graph API by means of OIDC on Azure is available on GitHub here: https://github.com/AlexandreFenyo/mitreid-azure
I am switching my application from Azure Active Directory authentication to authentication with Identity Server (using Azure AD as external auth). The authentication and authorization part is implemented and my web API successfully validates token and give me what I'm asking.
Our application also uses external APIs, such as Graph API and SharePoint Online which require Azure AD token. E.g. when I go to https://graph.microsoft.com/v1.0/me from my JS application with token that I get back from Identity Server, Graph API response is
401
{
"error": {
"code": "InvalidAuthenticationToken",
"message": "Access token validation failure.",
"innerError": {
"request-id": "ce7651bb-5dc4-49e9-90ff-02df440ed4ad",
"date": "2017-08-11T08:53:12"
}
}
}
I expected that because Identity Server is giving me his token, and not passing the existing token that is provided by Azure AD. I copied all the claims from Azure AD token into identity server token, but no changes.
What would be the right approach to enable my application to continue using APIs which require Azure AD token?
EDIT:
What I'm hoping for is this.
Click login button on Js (or any other client app)
Redirect to Identity Server login screen
Click on Azure AD external auth
Redirect to Microsoft login page and enter your credentials there
Redirect to Identity server app
a. I started Fiddler and see that "Microsoft" redirect to {IdentityServerAppUrl}/signin-aad (I suppose this is because I configured CallbackPath property on OpenID Connect options). This request carry a cookie idsrv.external. I'm not sure but I think inside is access token from Azure AD. I don't know how to decode this. I tried with base64, but it is not working.
b. When this request is finished redirect is made to {IdentityServerAppUrl}/account/ExternalLoginCallback. In this action method I check with debugger all fields and data in request but I can't find token from AAD. I'm hoping to get token and put it in additional calims.
Identity Server app redirect to JS client app with its own token and additional claim that contains Azure AD token that is valid on graph API and SharePoint.
First I would like to locate Action method or middleware that handle {IdentityServerAppUrl}/signin-aad?
Second, is there any way to get token from Azure AD or any other external provider inside {IdentityServerAppUrl}/account/ExternalLoginCallback Action method?
Be aware that I'm new to this kind of stuff and maybe I'm totally wrong with this thinking.
I manage to do Azure AD authentication without Identity Server, but know we have request to have multiple external providers and I'm hoping to handle all authentication in one app. If one day I get request to have additional external provider I need to add to just in one place.
You need to retrieve an access token from AAD for the Graph API - how that exactly works, check the Microsoft documentation.
Once you have that access token, you can return it as a claim in either the IdentityServer identity or access token (depending if you want to make it available to your front or back-end).
You can also try that first in a simple MVC app to remove the moving partsy - and once you have the AD part working, move your code to the app using the identityserver middleware.
I am also looking for an answer to this question. However, I think it should work a bit differently. IdentityServer gives you a JWT that you can use to authorize to the recources that make up your app. E.g.: yourAPI-1 and yourAPI-2. With the JWT you can pass on the identity. Microsoft Graph is an external resource. Therefore we would need the access token form the Graph API as a claim or external resource, same way as you'd receive an access token for an internal resource.
I would guess that there should be a way of forwarding whatever information you get from the identity provider (Azure AD) to IdentityServer for your client (JS app) to pick up. I am facing the same problem here.
There is another thread about this topic that caught my attention which I will look into. It requires to build your IdentityServer from the source with a few modifications: ASP.NET Identity (with IdentityServer4) get external resource oauth access token
I will let you know what the outcome is and push it to a git repo that you can use if it works: