I am trying to create a new web application that will be hosted in AWS. This application needs to authenticate users from our Azure Active Directory via OAuth2. Here's what I have working so far and steps I used to get me there:
1) I can generate a "code" after user logs in from "login.microsoftonline.com". To accomplish this, I set up a new application in Azure AD that my web application directs users to for logging in. I have also set up the API application in Azure AD which I'm using as the "resource" parameter in the query string when I direct users to the login.microsoftonline.com endpoint
2) using the "code" generated from #1 above, I can generate my authorization token by calling the /token endpoint of my application. I'm able to do this by passing the same resource value (the url to my API that I ultimately want to use), the code, my client id, and my client secret
3) the token response from #2 above sends down token_type, expires_in, scope, access_token, refresh_token, and id_token properties all of which have values. I'm able to decode the id_token into a JWT and it is showing the correct user information for the logged in user in the claims object
4) HERE'S WHERE I'M STUCK I then try to make a call to my API application that is also registered in Azure AD using the access_token I obtain in #3 above passing that value in an "Authorization" header with that value being "Bearer xyz123......" If I don't put any authorization on the API application, I get results as I'd expect, if however, I put an [Authorize] attribute on the class or even the Get() method, I always get a 401 (unauthorized). I'm certain there's something else I need to wire up I'm just not sure what. I found this resource: https://docs.microsoft.com/en-us/azure/api-management/api-management-howto-protect-backend-with-aad but it talks of registering my API with api management and I don't think I need to do that (I definitely don't want to if I don't have to).
The api I'm creating will rely on being able to get the logged in user's identity which I'm assuming I can extract from the bearer token, I just don't know how...
any help and guidance will be greatly appreciated.
Edit to include working solution:
Here is what i used in my startup class per the accepted answer below. Note the "audience" value is the URL of the API end point that I'm calling that I need access to. The Tenant is a custom url that we have bound in our organization, if you don't supply a valid tenant value, you might get an exception that says "Response status code does not indicate success: 404 (Not Found)." You'll need the Azure Active Directory assembly which you can get from Nuget: Install-Package Microsoft.Owin.Security.ActiveDirectory
public partial class Startup
{
// For more information on configuring authentication, please visit http://go.microsoft.com/fwlink/?LinkId=301864
public void ConfigureAuth(IAppBuilder app)
{
app.UseWindowsAzureActiveDirectoryBearerAuthentication(
new WindowsAzureActiveDirectoryBearerAuthenticationOptions
{
Audience = "https://myapi.azurewebsites.net/",
Tenant = "my.custom.url.com",
TokenValidationParameters = new System.IdentityModel.Tokens.TokenValidationParameters
{
ValidateIssuer = false
}
});
}
}
here are the post parameters I'm using to make the request from the application that needs access to receive my token.
body.Add(new KeyValuePair<string, string>("grant_type", "authorization_code"));
body.Add(new KeyValuePair<string, string>("code", code)); // code from response
body.Add(new KeyValuePair<string, string>("redirect_uri", "http://localhost:51015/redirect"));
body.Add(new KeyValuePair<string, string>("client_id", "xxxxxxx-8829-4294-b2c9-xxxxxxxxxx")); // client id of this application making the request
body.Add(new KeyValuePair<string, string>("client_secret", "PxxxxxxxxxxxxSnTJ4Uh63Voj+tkxxxxxxx="));
body.Add(new KeyValuePair<string, string>("resource", "https://myapi.azurewebsites.net/")); // same value goes here that is in the audience value of the api, this is also the same value that is passed in the resource parameter of the query string on the redirect to the login to obtain the "code" in the previous step