Accessing a .net core REST API from an outlook web addin using microsoft identity platform - asp.net-core-webapi

I have a .net core web REST api (.net 6.0) which uses microsoft identity platform to authenticate and authorize user access from a frontend. That is working fine.
Authentication is configured like this:
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAd"), subscribeToJwtBearerMiddlewareDiagnosticsEvents: true)
.EnableTokenAcquisitionToCallDownstreamApi()
.AddMicrosoftGraph(builder.Configuration.GetSection("MicrosoftDownstreamGraph"))
.AddInMemoryTokenCaches();
The same API should now be consumed by an outlook add-in. I obtain an access token using the office.js getAccessToken() function. If I call the API using this token, I receive:
Bearer error="invalid_token", error_description="The audience
'e1c50fba-abcd-4e63-9f54-xxxxxxxxxx' is invalid".
The AzureAD API registration for the add-in has the permission 'access_as_user' for the REST API.
My current guess is, that I have to use the on-behalf-of flow and the API needs to exchange the add-in token for an token that is allowed to use the REST API. Is this correct? Is there an easy way using Microsoft.Identity.Web to achiev this?
To my knowledge I should not return the exchanged access token to the add-in. So I would have to cache it inside the REST API and alter the the API request transparently such that it includes the correct token (obtained via obo flow). How can I achieve this?

The access token that is returned from the call to getAccessToken grants the host Office application (Excel, Word, etc.) access to the add-in; that is, to the add-in's web application. So, the audience of the token is the ID of the add-in in AAD. If the REST APIs were part of the add-in's web app, then that token would work, but if the REST API is a different web app (with it's own domain and AAD ID) then you would get the invalid audience error. You can either use the OBO (On Behalf Of) flow or the Auth Code flow to get a token with the REST API's ID as the audience, or redesign things so the add-in's web app and the REST service are the same domain and AAD ID. The web app would be serving up both the pages/scripts for the add-in AND exposing the REST API.

Related

Auth0 - API to be accessed by both users and other APIs

My project has an Angular frontend and a .NET backend. The .NET API is protected with auth0 using an authorization code with PKCE flow which the frontend has to authenticate against. However, the .NET API also needs to be accessible by a second external .NET API using machine credentials and the client credential flow. How would I go about setting up both of these authentication flows in one API, and how to tag each endpoint based on whether it is being accessed by the frontend or the external API?

Will MSAL be able to maintain a token cache and refreshes tokens for you when they are close to expire in case of Custom REST API secured by Azure AD

Based on the documentation details for MSAL (Azure AD) mentioned at : https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/wiki/MSAL.NET-supports-multiple-application-architectures-and-multiple-platforms#msalnet-is-about-acquiring-tokens-not-protecting-an-api
I am working on POC : ASP.NET Web App accessing Custom REST API protected by Azure AD.
The link mentioned above says that MSAL.NET (Microsoft Authentication Library for .NET) enables developers of .NET applications to acquire tokens in order to call secured Web APIs. These Web APIs can be the Microsoft Graph, other Microsoft APIS, 3rd party Web APIs, or your own Web API.
Based on the above definition is it good to assume that MSAL will be helping in maintaining a token cache and refreshes tokens for you when they are close to expire in case of the Custom REST APIs also.
Can anyone help me here by providing their guidance on it further.
MSAL and Azure AD don't give special treatment to MS Graph API tokens (except the ability to use a short name for scopes).
It can refresh any of the tokens as long as the way to refresh is still valid.
In the case of implicit grant (used by MSAL.js 1.x), the user must have an active AAD session in the browser.
In most other cases you use a refresh token to get a new token; as long as the refresh token is still valid, you can get a new token even after the access token has expired.

Proper OAuth2 authentication flow for a web API using the EWS Managed API

I've been reading through a bunch of documentation for using OAuth with Azure AD, but am still completely confused about how to properly implement things for my situation. Hopefully someone can steer me in the right direction.
I have created an ASP.NET Web API application that uses the EWS Managed API to access Exchange on behalf of different users. My application exposes endpoints such as /Mailbox/Messages and /Appointments with the intent that some front end web application will eventually use them to retrieve a user's emails and appointments. Currently the endpoints are working using basic http authentication, but I'd like to update them to use OAuth. The application has been registered in my Azure AD instance and I've configured it to require the "Access mailboxes as the signed-in user via Exchange Web Services" API permission.
Since the front end hasn't been implemented yet, I've been trying to test by manually calling the authentication endpoint. This prompts me to log in and provide consent. If I consent, I'm redirected to the callback URL that I provided when I registered the app with the authorization code contained in the query parameters. I'm still not quite sure how I'm supposed to be using this callback, but for the sake of testing I currently have the callback redeem the authorization code for an access token. This is done by calling the AcquireTokenByAuthorizationCode method on an instance of the AuthenticationContext class and providing my application's id and secret. Again, just for the sake of testing I return the access token to the browser. I can then call my aforementioned endpoints (after some modifications) with this access token and get the emails for the user. I'm guessing much of this is not the correct way to be doing things.
Some of my points of confusion:
What should the callback that I registered in Azure AD actually be doing when it gets the authorization code? Is this intended for a different type of application? Perhaps one that isn't just playing the role of a middle man.
I'm trying to make my application somewhat RESTful, so I don't want to have to maintain the access tokens on my end between requests. As such, does it make sense for my endpoints to expect that the access token be provided in the authentication header for each request? If so, does that mean the front end application should be responsible acquiring the access token and passing it to me?
Being completely new to OAuth and Azure, I'm not sure if any other details are pertinent, but I can provide more information as needed.
What you are implementing is this scenario: https://learn.microsoft.com/en-us/azure/active-directory/active-directory-authentication-scenarios#daemon-or-server-application-to-web-api
Here's how it works:
Your client app redirects the user to sign in at the authorization endpoint
Your client app gets back an authorization code (if using the auth code grant flow, there are others)
The client app exchanges the code for an access token for your API app
It will need to provide its client id and secret along with the code and the API's resource URI to get it
The client app calls to your API app, passing the access token in the Authorization header
Your API app then validates the access token, and requests for another access token from Azure AD for the Exchange API
It will pass the access token sent by the client app, along with its client id and secret and the Exchange API's resource URI to Azure AD
Your API app receives an access token so you can call to the Exchange API as the user
And to answer your two questions:
Authorization code flow is not used with APIs, only with apps that have a user signing in, thus the redirect URL is basically never used
Your API can and must expect and authenticate the access token for it to be in every request. But the access token it uses to call the Exchange API can and should be cached on the API's side. This is provided out-of-the-box with ADAL, though the tokens are only in memory.

Headless authentication with Azure AD (user/pass combination)

I'm following the guide and example provided by Microsoft here and I'm able to get the demo working, with the authentication happening in a console app, then making a request to a Web API with the correct token.
I'm looking to use this but the code in the console app would need to move to a Web App. Essentially: external server tries to access secure Web API, providing Azure AD username/password in the Authentication header of a HTTPS request. I pick up these credentials in the first insecure Web API, and attempt to authenticate the credentials against AD, obtaining the token. From here, I would then call the [Authorize]-protected Web API by making a request with the AD token.
At this point I'm using the same code from the example linked above, simply moving the code in the Console app up into the first insecure Web API controller, but I'm having no luck. I read on CloudIdentity that "You can only use those flows from a native client. A confidential client, such as a web site, cannot use direct user credentials.". Is this true? If so, is there another way to achieve my aim? I need to use the credentials as it may be likely that more services would use the API in the future, so each of these would need their own credentials to use that could be managed within Azure.
EDIT: In reading more around this, should I actually be aiming to use Client authentication, creating an "Application" within the Azure AD, and providing the client ID to each external service looking to call the API, to then authenticate with that, rather than credentials?
Yes, your edit is correct. The Resource Owner Password Credentials grant is meant to authenticate users, not applications. Typical use would be from an application that prompts you for username and password and then retrieves a token from Azure AD.
You can use the Client Credentials grant to get a token from Azure AD from a confidential client to call an API without user context. This flow requires that you register the application in Azure AD and generate a key (which will be used as the client secret). You can then use the ADAL library to ge a token from AAD as shown here.

Need Guidance Implementing OAuth 2.0 in ASP.NET App

I have created an ASP.NET application and an Azure-AD domain. Currently, I have the ASP.NET auth set up to hit the wsfed endpoint in Azure-AD. Everything works fine, but the problem is that this issues a SAML token and I need a JWT. From what I have read after much internet searching, I need to authenticate to the OAuth 2.0 endpoint of my Azure-AD domain. The trouble with this is that with everything configured the way it is, I always get back a 400 from this endpoint, likely because my config file is all set up for fed auth. My question is how do I configure my ASP.NET application so that it can talk to the OAuth 2.0 endpoint of my Azure-AD domain?
I need to use passive authentication.
Azure AD supports the OAuth2.0 flow that you can execute once the user has signed in using passive authentication, to receive access tokens to make delegated calls to WebAPIs on behalf of the user. You can use the Active Directory Authentication Library (ADAL SDK) to execute the OAuth flow. This sample application does exactly that: http://code.msdn.microsoft.com/AAL-Server-to-Server-9aafccc1
However, for your scenario, we recommend the OpenId Connect flow now, instead of SAML SSO + OAuth. With Azure AD OpenIDConnect flow, the Web Application receives an SSO token (JWT id_token) using which it signs-in the user, and also receives an auth code (OAuth auth code) that it can redeem for an Access Token (JWT access token) to access WebAPIs on behalf of the user. Azure AD provides an OWIN component that does this. This sample application should see you through: https://github.com/AzureADSamples/WebApp-WebAPI-OpenIDConnect-DotNet
Finally, refer to this help topic to find all authentications flows supported and recommended by Azure AD for your Web Apps/APIs and Rich-Client/Mobile Apps: http://msdn.microsoft.com/en-us/library/azure/dn499820.aspx
Hope this helps

Resources