We have developed Web API in .net Core 2.1 without authentication.
But now we are trying to add the Azure AD token based authentication.
we have registered app in azure AD and we did necessary changes in startup.cs file. and added authorize tag
When we test the API in postman we generated token we are getting Microsoft login page in Html format as result.
when we crosscheck the API in browser, its asking domain user name and password by providing the user name password we are getting the result.
Its seems some configuration or setting missing in Azure AD setup or code.
Can anyone help on this. other wise anyone share the steps for token based authentication implementation for API.
If you already have the api , you should firstly register an app in Azure Portal .
In your api application , you can follow the below steps :
Install the package Microsoft.AspNetCore.Authentication.AzureAD.UI
Register the Azure AD Bearer authentication service in ConfigureServices function :
services.AddAuthentication(AzureADDefaults.BearerAuthenticationScheme)
.AddAzureADBearer(options => Configuration.Bind("AzureAd", options));
In appsettings.json , set the correct api configuration from Azure Portal :
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"Domain": "YourDomain.onmicrosoft.com",
"TenantId": "cb1c3f2e-a2dd-4fde-bf8f-f75ab18b21ac",
"ClientId": "83bf146d-4948-4596-a4b3-b7b2e68ac3e0"
},
Tenant ID ,domain name and API's ClientId could be find in Azure Portal .Then you can add Authorize attribute on protected controllers/actions . If you have multiple authentication schema , you can authorize with a specific scheme .
You client app will uses the OpenID Connect middleware and the ADAL/MSAL to obtain a JWT bearer token for the signed-in user using the OAuth 2.0 protocol. The bearer token is passed to the web API, which validates the token and authorizes the user using the JWT bearer authentication middleware.
Related
I got SAML setup on my AD and I have the private and certificate PEMs along with the certificate and metadata and I want to know if it's possible to bypass the login from API? I'm developing a Node.JS API which I want to make requests to the server behind the SAML login but I need to bypass it with what I got.
Maybe a way to generate a token from Azure's API (to use as bearer authorization) would work like how you do it with OAuth?
I'm not asking for any other solution (like whitelisting etc.), I just need it to be token / API based
To bypass azure ad , you may chose for the On behalf flow.
For single-page apps (SPAs), here we pass an access token to a middle-tier confidential client to perform OBO flows instead.
This will only work, if the respective permissions (scope grants) are
already granted when you try to get an access token using the
on-behalf of flow.
Here API A authenticates to the Microsoft identity platform token
issuance endpoint and requests a token to access API B.
https://login.microsoftonline.com/<tenant>/oauth2/v2.0/token
with grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer
client_id=xxx
&client_secret=saxx1s
&scope=https://graph.microsoft.com/user.read+offline_access
&requested_token_use=on_behalf_of
Here we need to expose api and here I am giving user.read
And exposed api
The response has access token , refresh token
{
"token_type": "Bearer",
"scope": "https://graph.microsoft.com/user.read",
"expires_in": 3269,
"ext_expires_in": 0,
"access_token": "xx",
"refresh_token": "xxxx"
}
Please check Microsoft identity platform and OAuth2.0 On-Behalf-Of flow - Microsoft Entra | Microsoft Learn
Reference : how-to-use-azure-ad-access-token-to-bypass-microsoft-online-login
I have an Azure AD B2C tenant setup with an Angular app on the front-end using Authorization Code Flow with PKCE and a back-end api. Everything is working fine. I now have a need to allow the user to access certain pages on the front-end anonymously. I would prefer to still protect the apis these pages will call using the same access token.
I have followed the article here to set up Client Credentials flow. I am able to get an access token successfully using Postman and use it to call my back-end apis fine. However, when I try to do the same from the Angular app, I get the following error:
{"error":"invalid_request","error_description":"AADB2C99067: Public Client XXXXX-XXXXXX is not supported for Client Credentials Grant Flow\r\nCorrelation ID: 2b3346ef-1828-4900-b890-06cdb8e0bb52\r\nTimestamp: 2022-07-28 04:12:21Z\r\n"}
Below is the code snippet I am using in Angular to retrieve the access token.
const urlencoded = new URLSearchParams();
urlencoded.set('grant_type', 'client_credentials');
urlencoded.set('client_id', '<clientid>');
urlencoded.set('client_secret', '<clientsecret>');
urlencoded.set('scope', '<scope>');
const httpOptions = {
headers: new HttpHeaders({ 'Content-Type': 'application/x-www-form-urlencoded' }),
};
const url = 'https://<b2ctenant>.b2clogin.com/<b2ctenant>.onmicrosoft.com/<customPolicy>/oauth2/v2.0/token';
return this.httpClient.post(url, urlencoded, httpOptions);
Any ideas what could be missing?
Thanks!
Though azureadb2c supports client_credential flow.One may not use them with SPA apps.
This scenario is not supported by MSAL.js. Client credential flow/ grant type will not work in SPAs(Angular) because browsers cannot securely keep client secrets.
As they may end up in the browser, visible to everyone and to attackers that load them.
Note:As the application's own credentials itself are being used, they must be kept safe - never publish that credential in your source
code
If you are using it for web app , please make sure to select the platform as web or change the reply url type to be web.
"replyUrlsWithType": [
{
"url": "https......",
"type": "Web"
},
]
Please refer :
Configure authentication in a sample Angular SPA by using Azure
Active Directory B2C | Microsoft Docs
OAuth 2.0 client credentials flow on the Microsoft identity platform- Microsoft Entra | Microsoft Docs
Net core application. I have three applications registered in azure ad.
React SPA application
Web API Gateway application
Protected API application
Whenever user logs into SPA application, Redirecting to Azure AD with implicit flow to get access token.
I have received access token as below and used to access apis from gateway layer
{
"aud": "7851c317b-87e7-4cb3-95f0-37cb52b6f873",
"family_name": "alex",
"given_name": "fernandes",
"hasgroups": "true",
"roles": [
"Admin"
]
}
In the above token aud is client id of the spa application and other few details I added but not all the details.
Now I want to call Protected API application from Web API Gateway application
I am trying with sample http request in postman as below.
Request - https://login.microsoftonline.com/45fgh-f30d-4596-gt67-7045b338485a/oauth2/v2.0/token
Body
{
"grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer"
"client_id": "" //unknown client id of SPA or API GateWay or Protected API
"client_secret": "" //unknown client id of SPA or API GateWay or Protected API
"assertion": "Above token"
"scope":"" //unknown
"requested_token_use" : "on_behalf_of"
}
Along with above confusions, just wondering Is there any configurations required in azure ad in order to generate token for Protected API. One more thing is the token generated to access Protected API does that token have user details and role details same as above token generated by SPA?
Can someone help me in configuring On behalf of flow? I am struggling here to get this done. Any help would be appreciated. Thank you
As the following diagram shows, Client App means React SPA application, Web API 1 means Web API Gateway application, and Web API 2 means Protected API application. For more details, see this blog.
Steps of On-Behalf-Of flow:
Add API permission of Web API Gateway application to SPA application.
GET https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize
?scope={permission for Web API Gateway application like api://1108f6-xxxxxxx-9f622/test} openid
&redirect_uri={redirect_uri of SPA application}
&nonce=123
&client_id={client-id of SPA application}
&response_type=id_token token
Add API permission of Protected API application to Web API Gateway application.
It calls Microsoft Graph API in the official document, so the scope is 'user.read' in this step.
POST https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token
grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer
&client_id={client_id of Web API Gateway application}
&client_secret={client_secret}
&assertion={access token from previous step}
&scope={permission for Protected API application}
&requested_token_use=on_behalf_of
Call Protected API application with the access token
I have a background JS app that wont have any user input, so i was looking at using the app authentication without user input. I have set up an app in the Azure AD portal and also apps.dev.microsoft.com.
I am using the following endpoint:
login.microsoftonline.com/{Tenant}/oauth2/token
With the following body:
client_id: application_id
client_secret: generated key
grant_type: client_credentials
scope: "https://graph.microsoft.com/.default"
This generates an access_token however when i try and use it using the graph API, I get the following error
Access token validation failure
When investigating the token compared to a normal OAuth token with user input, i noticed its passing in roles rather then scp and the audience is my application rather then graph.microsoft.com.
What am i doing wrong?
The app registered in Azure AD portal works with Azure AD V1.0 endpoint ,app registered in apps.dev.microsoft.com that works with the v2.0 endpoint , Please firstly refer to this document for what's different about the v2.0 endpoint .
To use Azure AD v2.0 to access secure resources without user interaction(client credential flow) , you should send a POST request to the /token v2.0 endpoint:
POST /common/oauth2/v2.0/token HTTP/1.1
Host: login.microsoftonline.com
Content-Type: application/x-www-form-urlencoded
client_id=535fb089-9ff3-47b6-9bfb-4f1264799865&scope=https%3A%2F%2Fgraph.microsoft.com%2F.default&client_secret=qWgdYAmab0YSkuL1qKv5bPX&grant_type=client_credentials
You could refer to this document for how to use the OAuth 2.0 client credentials grant with Azure AD V2.0 endpoint .
If you want to use azure ad v1.0 (app registered in azure portal) with client credential flow, you could refer to this document . In azure ad v1.0 , you should indicate the resource parameter which the client app is requesting authorization for , in your scenario , the resource should be https://graph.microsoft.com/ if you want to acquire token to call microsoft graph api .
I have created a ASP.Net Web API (.Net Framework) app with "Work or School Accounts" as authentication type. This automatically registers this API app in my Azure subscription and I can see it under "App Registrations". I can see that Home Page Url is pointing to localhost address. I can see that API is launching locally on localhost address. I then launch Fiddler to get access token from Azure AD. My POST request to endpoint https://login.microsoftonline.com/<mytenant>.onmicrosoft.com/oauth2/token. has following 4 parameters
grant_type=client_credentials
&client_id=<appid from Azure AD Portal>
&client_secret=<secret from Azure AD Portal>
&resource=<appid from Azure AD Portal>
I get a token back. When I decode this token, I see aud and appid as expected(matching appid in Azure AD). I use this token as bearer token to invoke API call by adding Authorization: Bearer <mytoken> header in GET request to https://localhost:44374/api/values. However, this GET call to my API is returning me {"Message":"Authorization has been denied for this request."} error message.
What am I missing?
You should use App ID URI as the resource value when acquiring token , you could find the App ID URI in Properties of api app in azure portal ,like https://xxxxx.onmicrosoft.com/WebApplicationName . Web api will check whether the aud claim in access token matches the one you set in web.config :
app.UseWindowsAzureActiveDirectoryBearerAuthentication(
new WindowsAzureActiveDirectoryBearerAuthenticationOptions
{
Tenant = ConfigurationManager.AppSettings["ida:Tenant"],
TokenValidationParameters = new TokenValidationParameters {
ValidAudience = ConfigurationManager.AppSettings["ida:Audience"]
},
});
ida:Audience value in web.config is the allowed audience .