Setup:
ASP.NET MVC5 application (Full Framework NET 4.7) with Azure AD on top
WebAPI (Full Framework NET 4.7) with Azure AD on top
.NET ADAL 3.x library (not MSAL) used in both apps
In the Web App, in Katana, the OWIN middleware:
i authenticate the user (org account in a directory i control)
i then exchange Authorization Code for Access Token (with resourceId: https://graph.microsoft.com)
i place the resulting Access Token in user claims
Now everything is fine and dandy, i can use the Access Token as Bearer and call Microsoft Graph and get /me user profile, picture and what not.
But how do i call my own Azure AD protected API from my Web App?
I can't just exchange the Authorization Code a second time for a different resourceId. I could context.AcquireTokenAsync() with app_id and app_secret, but the JWT i get back does not contain any user identifying claim, so now my API doesn't know anything about the calling user, it only knows that the confidential client (my Web App) did indeed present a valid token.
How do i request a token that will successfully call my API that will return some sort of user claims? The user principal name or user id is probably enough.
Should i just move all the Microsoft Graph calling logic to the WebAPI and exchange Authorization Code for my API's resourceId, or is there an in-place solution to my conundrum? What's the right pattern here? Ok not right, maybe just better.
You can request for a second access token with the same authorization code for another API.
Depending on how you request the access token, the audience of the token might be either the client id or Application ID URI of the API. So you must make sure that both are accepted audiences in the API.
In the case of ASP.NET Core APIs, you can add the following in JWT Bearer authentication config:
TokenValidationParameters = new TokenValidationParameters
{
ValidAudiences = new [] { "https://blabla", "g-u-i-d" }
}
Related
I have the following configuration in my ASP.NET Core Web API:
// Adds Microsoft Identity platform (AAD v2.0) support to protect this Api
services.AddMicrosoftIdentityWebApiAuthentication(configuration);
services.AddControllers(options =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.RequireClaim("email")
.Build();
options.Filters.Add(new AuthorizeFilter(policy));
});
I have an Angular client application that sends the AuthToken with each request.
Below is my asp.net WEB API controller
[Route("[controller]")]
public class UserController : ControllerBase
{
[HttpGet]
public IActionResult Get()
{
//Get User Email ID from Claims
//Get User details from Database
//Return the User Details
...
}
}
In the asp.net WEB API controller, I need to get the Email claim from the Auth Token.
Should the AngularJS application send the AuthToken or IDToken? When do use ID token vs Auth Token?
Update :
OpenID Connect is built on top of OAuth2.
WEBAPI:
An access_token is useful to call certain APIs in Auth0 (e.g. /userinfo) or an API you define in Auth0.
WEBAPP:
An id_token is a JWT and represents the logged in user. It is often used by your app.
CONSOLE/MOBILE APP :
A refresh_token (only to be used by a mobile/desktop app) doesn't expire (but is revokable) and it allows you to obtain freshly minted access_tokens and id_token
My question still remains the same? If the webapp or console app requires the claims, should we need AuthToken?
Update:#2
https://www.youtube.com/watch?v=M4JIvUIE17c
Please note that, access tokens are used to perform actions like authentication and authorization to protect the web APIs.
ID tokens are generated by authorization server and contains the claim of the user information, and these claims can be used for the UX in your application.
AFAIK as your application sends the AuthToken with each request you can use the same token to get Email claim.
Make sure to add email API permissions like below:
Go to Azure Portal -> Azure Active Directory -> App Registrations -> Your App -> Api Permissions
Try to give the scope = api://{app id of the AAD app which represents the web api}/.default openid as mentioned by Allen Wu in this SO Thread.
I tried to generate an access token with above scope and got the claims successfully like below:
Please note that, you can get the email claim either by using AuthToken or IDToken.
I am working on the ASP.NET MVC 5 web application. It has only one layer which contains views as well as business logic/operations. Business logic is logically separated from UI but it is not behind a separate web service/API layer.
Now when I use OIDC and OAuth2.0 for my application, there is no separate Resource Server, so to say. Because Client itself has all the Resources I want to have access to.
I am using Authorization Code Flow for authentication & authorization.
Questions:
Does access token have any role in this case? If yes, what?
How am I going to practically use the access token? Since the client itself is the resource server, there is nothing to which I need to send access token to.
I guess you get an ID token which contains all the information you need for authentication of a user. If not, you can use the access token to get the user info. If this is all the information you need, then the access token is not needed anymore. This happens, because OAuth2 is a permission delegation protocol, not an authentication protocol in a first place.
When you have the user info, you can implement between the browser and your ASP.NET backend in any way. You can take a look at the OAuth 2.0 for Browser-Based Apps RFC.
In this case you should use Client Credential flow instead of Authorization Code flow.
In Client Credential flow, your application would send your client id & client secret to Authorization Endpoint directly and asking for access token. Authorization Code is not needed in Client Credential flow. Details as below
An authorization code flow typically need your client redirect
resource owner to authorization endpoint and get a authorization
code from authorization endpoint, client than uses this code to get
access token, at the end of the day client uses access token to
access protected resource.
In Client Crendential flow. your client app is actually the owner of
your resource. So no need to asking for a authorization code. direct
uses its own client credential to get access token from
authorization endpoint and use that access token to access protected
resource(Resource server)
Im a bit confused about oauth2 and OIDC.
So supposedly with OIDC we now get the id_token which uniquely identifies the user in the same oauth2 flow.
But my understanding is - oauth 2 came out earlier than OIDC and OIDC support is not universal even at this point.
So how do current APIs that use oauth2 (without OIDC) work?
Let's say there is a mobile app that needs to use some API.
Is the idea that after mobile app get's oauth2 access token -> they always have to hit some endpoint like /me using that access token which will then provide user id information? and thus the api has to track which access tokens have been given to each particular user?
Sry this question comes out like request for some trivia info - but Im really new to oauth2 & OIDC and just trying to understand and make sure im not missing anything....
OAuth 2.0 NOT an Authentication protocol.
OAuth 2.0 is more of a delegation protocol where the Resource Owner delegates certain permissions to a OAuth Client.
OIDC is an Authentication protocol built on top of OAuth 2.0.
OAuth 2.0 should be used where a user (Resource Owner) is delegating permissions to an Application (OAuth Client) to perform some action.
OIDC should be used where an an Application (OAuth Client) needs to some "Level of Assurance" that the user (Resource Owner) is who he says he is.
The Authentication is done by a Third-Party (Authorization Server). The id_token allows the Client to access information about the user that the Authorization Server knows about (and hopefully has performed some verification).
As jwilleke answered it, OAuth 2.0 is for authorization. OpenID Connect (OIDC) is built on OAuth 2.0 adds Authentication layer.
Basically, OAuth 2.0 delegate the client application to access a protected endpoint on-behalf of the resource owner. In simple words, end user authorise the application access a resource/service. In this process, application does not receive any detail about the end user so it cannot authenticate/detect(In OIDC, application receive the id token, which is self-sufficient enough to authenticate the end-user) end user.
Q : Is the idea that after mobile app get's oauth2 access token -> they always have to hit some endpoint like /me using that access token which will then provide user id information? and thus the api has to track which access tokens have been given to each particular user?
From OAuth 2.0 perspective, there is no end user information sharing. But the token issuing identity provider understand the tokens it issued. Internally it can map end user details, permissions and anything it requires to process it. With that, when the API (resource server) receive the access token, it can validate the token. Note that resource server and authorization could be the same or different. And these are implementation specific details. Alternatively one could use token introspection as defined in rfc7662 to detect validity of issues access tokens.
Example scenario
You have mobile app A. And it have the ability to use a service B (protected by Access tokens) which is exposed by service provider G. Assume there is a user Alex who have already registered at SP G so have access to service B and uses app A. And SP G have OAuth 2.0 implemented so service B accepts access tokens issued by SP G.
User Alex use App A and there is a functionality in the App A which need to consume service B. App A require authorisation from Alex to consume service B on-behalf of him/her. In doing so, there will be a user login process and at the end SP G issue access token to App A. Does it convey identity of Alex ? No it does not. But App A can now consume service B using access token it received. Service B fully understand and can validate access tokens issues by SP G. IMO This is OAuth 2.0 in nutshell.
p.s - Substitute known services like Google calendar, Google identity and your android app so that it make more sense.
Background
I have a MVC 5 Web App and hosted in Azure App Service as Web App and secured with Azure AD; Anybody with valid AD credentials can authenticate themselves and view all HTML Content in the Web App;
Objective
I need to give just one of these MVC-View to outside individuals to view. For such we have already created an User in Azure AD which we will be sharing the details with the outside world. Hence, the thrid party will need to write some code to authenticate to our Azure AD and view this HTML content non interactively (Which means without allowing the third party app to prompt to enter user credentials from Azure AD).
What I have thought about
Assume that I am the third Party, I am going to authenticate to Azure AD from a Console/WinForms/HTML
Page and get myself a token; Then I will be using the token, to open
up a Browser to view this page.
Challenges I see
Session Expiration
Session Validity
Putting everything intto a Picture
Please show me some guidence to accomplish the objective.
Hence, the thrid party will need to write some code to authenticate to our Azure AD and view this HTML content non interactively (Which means without allowing the third party app to prompt to enter user credentials from Azure AD).
Per my understanding, you could leverage the OAuth 2.0 Client Credentials Grant Flow by using the client_id and client_secret.
Also, you could use OAuth 2 Resource Owner Password Credentials grant. Note: The resource owner password grant doesn't provide consent and doesn't support MFA either. Detailed tutorial, you could follow here.
Based on the authentication implementation part in your Web App, you could follow the approaches below to implement your scenario:
For using App Service Authentication / Authorization
You do not need to modify any code in your Web App project.
For using Microsoft.Owin.Security.OpenIdConnect middleware
You could use Microsoft.Owin.Security.ActiveDirectory package in your Web App for supporting AAD bearer token authentication, and this middleware need to be configured before the other authentication middlewares as follows:
app.UseWindowsAzureActiveDirectoryBearerAuthentication(
new WindowsAzureActiveDirectoryBearerAuthenticationOptions
{
Audience = "{the-AAD-clientId}",
Tenant = "{TenantId}"
});
//app.UseCookieAuthentication
//app.UseOpenIdConnectAuthentication
For the client (the third Party), they could leverage the above two flows (Client Credentials Grant Flow ,Resource Owner Password Credentials Grant Flow) to retrieve the access token without user interaction. Then they could access the specific view page by using the token as follows:
Get https://{your-app-name}.azurewebsites.net/home/index
Header Authorization:Bearer {the-AAD-accessToken-or-IdToken}
For retrieving the token, you could follow this tutorial for using User Password Credential flow. For Client Credential, you could just construct the ClientCredential instance when invoking AcquireTokenAsync for getting the token.
Additionally, you could create a new AAD application for this scenario or just use the AAD application for your current Web App. Moreover, there may exists risks when exposing the username & password or clientId & ClientSecret to the third Party, I would recommend you expose a new endpoint for generating the token in your Web App backend and return the token to the third party for security consideration.
I am working on an ASP.NET Core 2.0 API. Currently this API supports a Service to Service workflow where the client console application obtains an access token from Azure AD using their console application's Azure AD app registration AppId/AppKey values.
To support this, my API uses...
// Add Azure AD OAUTH2.0 Authentication Services
services.AddAuthentication(sharedOptions =>
{
sharedOptions.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddAzureAdBearer(options => Configuration.Bind("AzureAd", options));
in Startup.cs ConfigureServices method and...
app.UseAuthentication();
in the Startup.cs Configure method. And finally the ...
[Authorize]
attribute along with the...
using Microsoft.AspNetCore.Authorization;
using statement in my controllers.
This is all working fine right now.
However, I now have a need to allow an admin web app to access my API. This admin web app will use Azure AD to authenticate the user login and obtain an Identity Token. I want my API to also be able to accept this Identity Token to;
Allow access to the API, and
Allow my API to identify the user and make decisions in the API
based upon the user identity's claims.
Can ASP.NET Core 2.0 support both access token and identity token without breaking what I currently have working with the service to service workflow?
That should work fine - your above breakdown needs some minor tweaks though:
THE CONSOLE APP
Gets a simple access token based on an API key - the access token is NOT user specific and represents the application identity.
THE ADMIN WEB APP
Users login and get an id_token AND an access_token. The id_token is just used by the web app as proof of authentication and never sent anywhere.
The access_token is user specific and can be used to call the API and get personalized data.
THE API
The job of the API is to receive access tokens and authorize based on claims from the token. For the console app the claims will only contain the application identity via a 'client id' claim. For the web app you will also be able to identify the user - most commonly via a 'sub' claim (there may be other user claims such as email).