MobileServiceClient InvokeApiAsync gets 401 while try to access asp.net core web api - azure

I have a Xamarin Forms app that intereacts with a Asp.net Core Web api hosted on Azure App Service with client authentication flow with Azure B2C authentication.
The app can login succesfully to the Azure with the LoginAsyc (I get the idtoken) but when I try to invoke a service that requires authorization using the MobileServiceClient I get a 401. The api is called using the InvokeApiAsync.
If I invoke a an api method that does not require authorization it works fine.
I opened the Azure logs, and only see 401 error.
Any idea how to call this secure action method from Xamarin using the MobileServiceClient.
Please help
David

The app can login succesfully to the Azure with the LoginAsyc (I get the idtoken) but when I try to invoke a service that requires authorization using the MobileServiceClient I get a 401. The api is called using the InvokeApiAsync.
According to your description, I assumed that you are using App Service Authentication / Authorization. For Client-managed authentication, you directly contact the AAD identity provider and retrieve the id_token or access_token. At this time, you could just access the authorized endpoint as follows:
https://{your-app-name}.azurewebsites.net/api/values
Authorization: Bearer {aad id_token or access_token}
Note: When constructing the MobileServiceClient, you could pass your custom DelegatingHandler to append the bearer token before sending request(s) to your Azure backend.
I just created a single Native app in my B2C tenant and use MSAL to retrieve the id_token or access_token as follows:
var authority = "https://login.microsoftonline.com/tfp/{Tenant}/{Policy}";
PublicClientApplication IdentityClientApp = new PublicClientApplication("{native-app-id}", authority);
IdentityClientApp.RedirectUri = $"msal{native-app-id}://auth";
var scopes = new string[] {
//"https://bruceb2c.onmicrosoft.com/EasyAuthB2CApp/user.read"
""
};
var result=await IdentityClientApp.AcquireTokenAsync(scopes);
Note: I just created a single native app, the parameter scopes in AcquireTokenAsync method does not support the clientId, so I just pass the empty scopes, at this point, you would not receive the access_token, you just need to use the id_token as the bearer token to access your Web API. For the Web API web app, I used the native app to configure my AD authentication on Azure Portal.
Moreover, you could create a native aad app for your mobile client and a WebAPI aad app for your azure web app. At this time, you could specify the valid scopes for your native aad app to access the WebAPI app. Then, you would retrieve the access_token, at this time you need to set the WebAPI app id as the Client ID or add it to the ALLOWED TOKEN AUDIENCES list on Azure Portal.
In summary, you need to make sure the aud property in the id_token or access_token matches your Azure Active Directory Authentication Settings on Azure Portal. Note: You could use https://jwt.io/ to decode the token and check the related properties.
Moreover, for client flow authentication using LoginAsync, you need to pass the access_token to log in with your web app, then you would retrieve the authenticationToken. And the mobile client library would add the authenticationToken as the x-zumo-auth header to the subsequent requests (e.g. using MobileServiceClient.InvokeApiAsync).
Additionally, here are some tutorials, you could refer to them:
App Service Auth and Azure AD B2C
Integrate Azure AD B2C into a Xamarin forms app using MSAL
Azure AD B2C: Requesting access tokens
ASP.NET Core 2.0 web API with Azure AD B2C using JWT Bearer middleware

Related

Azure AD B2C Resource Owner Password Credentials Authentication

In my application I want to call Azure Web API using Resource Owner Password Credential flow. I have implemented Azure AD b2c Auth for my Web API. I have created 2 Application in Azure, one for Web API and Native client App for ROPC. I gave WEB Api Access in ROPC app. I followed this article and got the Token from ROPC app. But when i pass my ROPC token to Web API I am getting 401. I dont know how to pass the scope of my web api scope in ROPC Token Request. Any help would be appreciated
Thanks in Advance,
Subbiah K
When you are requesting /token from Native APP (ROPC flow), you can add scopes in the request.
From the doc scope default set to
openid <ApplicationId/ClientId> offline_access
Modify this to like below to add scopes from Web API app. Make sure you should not put ClientId in scope
`openid https://tenant.onmicrosoft.com/hello/demo.read https://tenant.onmicrosoft.com/hello/user_impersonation offline_access`
Hope you already given API access (scopes) to Native Application.
Once you get access_token, that token will contain all the scopes you requested and you can send this to Web API to authorize.

How to generate oauth token for webapi without using client id and client secret

I have deployed one webapi into azure. After that I have register my API into Azure AD.
I got my API client-id and client-secret, now i just want to test my API not like
3rd application will access it so what will be recourse id in this case.
I have used oauth for authentication into that webapi.
I want to test that webapi so into POSTMAN i used this url to generate oauth token
which i will pass as header Authentication bearer token.
step 1 -
https://login.microsoftonline.com/{{OAuth_Tenant}}/oauth2/token
in header -
grant_type:client_credentials
client_id:{{client_id}} // i have my API client-id
client_secret:{{client_secret}} // i have my API client-secret
resource:{{resource}} // i have my API client-id
when i generate token using above values and send that bearer token it fail error unauthorized.
You need to register an app in Azure Active Directory to acquire access tokens.
Register an app there, and you can find the client id/application id there.
Then you can create a key for the app, that's your client secret.
Finally the resource should be the client id or app id URI for your API's app registration in Azure AD.
To implement this according to best practices, you'll also want to look into defining app permissions for your API, so you can then assign privileges to apps to call your API.

Accessing MS Graph from API on behalf of user currently signed in to separate web client

I am developing an API(ASP.NET Core) which is accessed via separately hosted web client(React), both hosted on azure as app services.
Client app must have auth based on azure Ad(single tenant, preferably secured by azure auth based on aad).
When the user signs in to client the API must have access to MS Graph on behalf of user. Obviously both resources must be secured, I have tried using azure auth based on AAD on both app services, but I couldn't get a token to MsGraph in this approach with the token obtained from auth to ADD on API side.
Question is, how to avoid passing token to MsGraph with token for azure aad auth from client, and obtain token for msGraph based only on token from aad auth while having only one place for users to sign in and keep both app services secured?
I am using nugget for MsGraph on Api side to interact with MsGraph. I haven't found any sample that refers this specific case.
Scenario: Your application's Web API (protected by Azure AD) receives auth token from a client application (React) and needs to call a downstream Web API (Microsoft Graph) on behalf of the signed-in User.
Conceptual Documentation on Microsoft Docs: Your scenario exactly matches the OAuth 2.0 on-behalf-of flow as explained on Microsoft Docs for Azure AD here Service-to-service calls that use delegated user identity in the On-Behalf-Of flow
Code Samples:
Service to service calls on behalf of the user (From Azure-Samples on GitHub)
Calling a downstream web API from a web API on behalf of user (From Azure-Samples on GitHub)
Using Azure AD On-Behalf-Of flow in an ASP.NET Core 2.0 API (Not directly Microsoft samples, but from Joonas W's blog, who is an MVP)
Important Code
This is how you use the already passed in token to acquire a new token, with which to call the Microsoft Graph API, from your Web API, on behalf of the user.
Preparing the User Assertion:
ClientCredential clientCred = new ClientCredential(clientId, appKey);
var bootstrapContext = ClaimsPrincipal.Current.Identities.First().BootstrapContext as System.IdentityModel.Tokens.BootstrapContext;
string userName = ClaimsPrincipal.Current.FindFirst(ClaimTypes.Upn) != null ? ClaimsPrincipal.Current.FindFirst(ClaimTypes.Upn).Value : ClaimsPrincipal.Current.FindFirst(ClaimTypes.Email).Value;
string userAccessToken = bootstrapContext.Token;
UserAssertion userAssertion = new UserAssertion(userAccessToken, "urn:ietf:params:oauth:grant-type:jwt-bearer", userName);
Acquiring a token for Microsoft Graph:
result = await authContext.AcquireTokenAsync(graphResourceId, clientCred, userAssertion);
I ended up with using only Azure Ad + auth validation by code(no azure auth).
The API uses OBO flow, the client app uses implicit flow.
Basically two separate app registrations on aad, the client which has access_as_user permision to the api, and the other one for api which has permissions for MsGraph. You configure it in App registrations(preview)/API permissions. (For detailed guide follow examples below, start with the api)
For Web client I also used scopes: 'access_as_user', 'offline_access', 'openid' in the request for the token, added true for "oauth2AllowImplicitFlow" in manifest and redirect to the yourdomainname.azurewebsites.com, the rest of configuration similarly to the native client in example below.
Useful resources:
API:
https://github.com/Azure-Samples/active-directory-dotnet-native-aspnetcore-v2
https://learn.microsoft.com/en-us/azure/active-directory/develop/v1-oauth2-on-behalf-of-flow
(I recommend testing with native client first to check if its set up correctly,
configuration of API will remain the same for separate web client)
Web client:
https://learn.microsoft.com/en-us/azure/active-directory/develop/v1-oauth2-implicit-grant-flow
This is solution which suits me at the moment, it might be possible to tailor it better.

Authenticate Azure app service with AAD custom login in mobile app

I have created app service for mobile app. Then i have added Authentication to the app service. Then Selected Authentication type as "Log on with Azure AD". It is working fine.
Is it possible to have custom login page instead of browser based login screen?
I was able to get the token by using https://login.microsoftonline.com//oauth2/token. But not able to authorize the app service with this bearer token.
Is it possible to have custom login page instead of browser based
login screen?
This page is the authentication endpoint of AzureAD. Though it can be configured by Company branding, I think it cannot be customlized by yourself for Moblie APP.
I was able to get the token by using
https://login.microsoftonline.com//oauth2/token. But not able to
authorize the app service with this bearer token.
Authencation/Authorization for Web App is a feature that securing Web App behind those IDPs, NOT just like other azure resources you can use REST API to access it. I understand what you want to do . But this action is not recommended or supported.
I was able to get the token by using https://login.microsoftonline.com//oauth2/token. But not able to authorize the app service with this bearer token.
As juunas answered, your token may does not match the AAD provider you configured on Azure Portal. Details you could follow here to check your configuration. Moreover, you could use https://jwt.io/ to decode your access_token and validate the related properties (e.g. the aud should be the clientId you configured on Azure Portal,etc.).
As App Service Authentication / Authorization (EasyAuth) states as follows:
Users who interact with your application through a web browser will have a cookie set so that they can remain authenticated as they browse your application. For other client types, such as mobile, a JSON web token (JWT), which should be presented in the X-ZUMO-AUTH header, will be issued to the client. The Mobile Apps client SDKs will handle this for you. Alternatively, an Azure Active Directory identity token or access token may be directly included in the Authorization header as a bearer token.
For Azure Web App or Azure Mobile App, you could just access your endpoint as follows:
https://{your-app-name}.azurewebsites.net/api/values
Header: Authorization:Bearer {the id_token or access_token of AAD}
Or
https://{your-app-name}.azurewebsites.net/api/values
Header: x-zumo-auth:{authenticationToken}
Moreover, if you retrieve the access_token in your mobile app, you could also use it to retrieve the authenticationToken and use the authenticationToken for communicating with the backend endpoint.
POST https://{your-app-name}.azurewebsites.net/.auth/login/{provider-name,for your scenario, it would be AAD}
Body: {"access_token":"<your-access-token>"}
For your mobile client, you could use the client for Azure Mobile Apps, details you could follow here. Also, you could follow Authenticate users to understand the client-flow and server-flow authentication for App Service Authentication.
As Wayne Yang said, customization of the login page is limited to logos and some text.
I'm not sure if you can use the "Easy Auth" for APIs.
You might need to actually implement the authentication in your app.
In that case your API would validate the incoming JSON Web Token so that its signature is valid and that the audience and issuer are what is expected.
Most frameworks have JWT authentication available, so it mostly comes down to configuring that properly.

Azure client app accessing Azure api secured by AD

I have an Angular 5 app and a web api app, both of which are hosted in Azure.
They have been secured with Azure AD at the website level e.g. no anonymous access is allowed.
When browsing the Angular site, it asks me to log in fine and I can access .auth/me which uses the local cookie to get token/claim information.
I now want to call the separate api but not sure how to go about it.
Both sites have an application in Azure AD, and I've set the client to have delegated permissions of 'Access to API'.
I've tried accessing the api using both the local cookie from the client (not sure if this would work) and the token returned .auth/me but neither work.
In my client manifest I have the following:
"resourceAppId": "3cddd33c-2624-4216-b686-7f8fa48f38cf", // api id
"resourceAccess": [
{
"id": "c2712c68-ea93-46d2-9874-61b807b19241",
"type": "Scope"
}
]
but haven't seen any additional scopes added to the claims, should it?
According to your description, you have both created the separate AAD application for your Angular app and your web api app, and configured the delegated permissions for your Angular AAD app to access the web api AAD app.
Based on my understanding, you are using the build-in App Service Authentication / Authorization for authentication, at this point you could do not need to change code on your app backend. You may have set Action to take when request is not authenticated to Log in with Azure Active Directory instead of allowing anonymous access, at this time your app service would directly redirect the user for authentication. After logged, your client could access https://{your-angular-app-name}.azurewebsites.net/.auth/me for retrieving the logged user info. For accessing your web api website, you could just send the request as follows in your angular client:
GET https://{your-webapi-app-name}.azurewebsites.net/api/values
Header Authorization:Bearer {id_token or access_token of AAD}
UPDATE:
That is exactly the route I'm trying to implement. One thing missing though, I had to add the client application id to the allowed token audience of the api app in Azure.
For retrieving the access_token, you need to set additional settings for the AAD provider in your Angular web app as follows:
"additionalLoginParams": [
"response_type=code id_token",
"resource=<AAD-app-id-for-your-webapi-webapp>"
]
Details you could follow this similar issue.
Use the EasyAuth server flow for logging, you would get the access_token, and you could leverage https://jwt.io/ to decode your token as follows:
Pass the access_token as the bearer token to your webapi web app, at this time you do not need to specific the ALLOWED TOKEN AUDIENCES.
At this time, you could invoke .auth/refresh against your Angular web app for refreshing the access_token, then you could use the new access_token to access your webapi web app.
I want roles included in the token so might have to stick with id?
If you want your Web API exposing access scopes to your Angular application which would be contained in the access_token as the scp property, you could follow the Configuring a resource application to expose web APIs section in this tutorial. Moreover, you could also follow Application roles.
UPDATE2:
You could follow Authorization in a web app using Azure AD application roles & role claims for detailed tutorial and code sample.
The usual approach would be to use ADAL.JS (or MSAL.JS with AAD v2 endpoint/B2C) to get an access token for the API.
ADAL.JS uses a hidden iframe to get an access token using the user's active session in Azure AD.
You can find an example Angular app here: GitHub.
An especially important part of the ADAL.JS configuration is here:
var endpoints = {
// Map the location of a request to an API to a the identifier of the associated resource
"https://myapi.azurewebsites.net/": "https://myaadtenant.onmicrosoft.com/MyApi"
};
The property name/key should be the URL for your API. ADAL-Angular detects calls to URLs starting with that, and attaches the correct access token to them.
The value should be the App ID URI of the API. You can find it from your API's App Registration from Azure Active Directory -> App registrations -> All Apps -> Your API -> Settings -> Properties.
You do need to enable implicit grant flow on the Angular app from the app registration for the SPA. You can find it from the Manifest.

Resources