I have enabled Azure App services authentication and registered my function in AAD, and the client then uses OAUTH2 to get a token and then call the API using that token and this works fine.
But I am struggling to find the documentation about how I based on that token can get the Client Application name that the client used to authenticate in my code
Let’s say my function app is testauth and the client app for the mobile app is clienttest
They use the clientID and clientSecret from the clienttest to auth to the resourceId of testauth
So now in my C# code I want to know the name clienttest is that possible and if so how?
I read about claims but I cannot really put the puzzle together
You can get the clientID of clienttest. If you manage a map of the client name to clientID in your function app, then you will be able to know the client name.
1. You can get the token from http header. Here is the official documentation: Retrieve tokens in app code
AS you are using AAD as the provider, so you may get the access token from http header: X-MS-TOKEN-AAD-ACCESS-TOKEN
2. Then you can decode the token. It is a JWT, which contains 3 parts: header, payload and signature.
All of them are base64url encoded, and are concatenated using periods. So, you can either use popular JWT libraries to decode it or just base64url decode the payload part. Then you will get a JSON string. Finally, you can get the appid claim:
With the appid claim, you will know the client name.
Update
You can get app name you registered in Azure AD with Graph API
With $filter expression, you can get app details. Here is a sample request: https://graph.microsoft.com/v1.0//applications?$filter=appId eq '68a1189c-a6b0-48fe-908c-841916d72731'
And you will get the following response:
You can see that the app's display name is included.
Related
Actors:
Black box (MS Power App custom connector) with user logged in
API A - .NET Standard WebApi with [Authorize] attribute and AAD authorization enabled (no additional verification in code), ida:audience="A" in web.config
API B - .NET Standard WebApi with [Authorize] attribute and AAD authorization enabled (no additional verification in code), ida:audience="B" in web.config
API C - .NET Standard WebApi with [Authorize] attribute and AAD authorization enabled (no additional verification in code), ida:audience="C" in web.config
Flow:
Power App connector calls API A. Within the code of API A (C#) I can decode JWT from Authorization header and see which user is logged in. Now, I have to call API B and API C and then return something to Power App connector. API B and API C must be able to also decode JWT and get UPN from token.
Problem:
When I tried to reuse whole Authorization header (just get it within API A and add to HttpClient to call API B and C) I get 401.
Now I know that was because of ida:Audience value. I suppose it is part of .NET framework verification, beyond my control. When I changed ida:Audience in API B and C to "A" it worked. But it was only for testing purposes, I am not allowed to do it in production.
Then I tried to set scopes in Power App connector to multiple values (delimited by space) with different audiences - no luck, error from AAD, multiple audiences not allowed.
So, my question is: is it possible in my scenario to do what I need? I have only access token for audience A and have to authorize (with impersonation) in endpoints with other audience value.
This is exactly what the on-behalf-of flow is for.
It allows API A to take the access token it received and ask for an access token to API B (with the same user info in the token).
More info on the flow: https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-on-behalf-of-flow.
Example request content from documentation to token endpoint that uses a client secret:
//line breaks for legibility only
POST /oauth2/v2.0/token HTTP/1.1
Host: login.microsoftonline.com/<tenant>
Content-Type: application/x-www-form-urlencoded
grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer
client_id=535fb089-9ff3-47b6-9bfb-4f1264799865
&client_secret=sampleCredentia1s
&assertion=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6InowMzl6ZHNGdWl6cEJmQlZLMVRuMjVRSFlPMCJ9.eyJhdWQiOiIyO{a lot of characters here}
&scope=https://graph.microsoft.com/user.read+offline_access
&requested_token_use=on_behalf_of
Using MSAL.NET is definitely better than using the HTTP endpoint directly though.
You would replace the scope in this request with a scope from API B.
I want my Web API to get an Access Token to then call Microsoft Graph API. I've gone through a few documents and threads but they all talk about a POST method that asks for a Client ID and App Secret created when registering the app on AAD.
I'm following this document here.
My problem is:
What is client_credentials? Where should I get it from? I thought the API is supposed to be working with the secret and the client I'd only.
I appreciate your help.
There's 4 parameters in the HTTP request:
grant_type: in this case, the value is "client_credentials"
client_id: The client id of your app
client_secret: The client secret of your app
resource: The identifier of the API you want a token for, in this case https://graph.microsoft.com
So only client id and secret are needed from your app.
If you use v2 endpoint / MSAL, note there is no resource parameter.
Instead you would use scope=https://graph.microsoft.com/.default.
I'm trying to work with the OAuth bearer tokens Web API 2 supplies but I don't know how to unencrypt them or get the data out.
What I'd really like to do is either find or write myself an equivalent tool to this Google Tool https://developers.google.com/wallet/digital/docs/jwtdecoder for the tokens I am getting from Web API. The Google tool allows you to paste in the string of text representing a JWT token and it splits it up and unencodes the JSON within.
In Visual Studio 2013 if you choose New ASP.NET project, and then choose the Web API template with individual user accounts you get a sample project that contains a token endpoint. If you start the project, you can then POST a request "grant_type=password&username=joe&password=joe" to /token on the built in webserver and you get a token back:
{
"access_token":"x3vHm40WUXBiMZi_3EmdmCWLLuv4fsgjsg4S5Ya8kppDY_-2ejn7qF5Y_nbQ0bYVIKl6MNzL2GtXv-MAuwjippAAv5VDaxoKdxEVxeFrQ_eXsKNaQK7IvmVs1rIZ9eeRfRGK2AQ59wWQcyTtYO0dPJx9K7PGrSKz4ADAZ9SEZqQ4IesVhYbRCwToyxoyU5L9qdU8jXdHumkIrULRQhf68rIaBrEA_Be-V0rzWJ644fRLvv3z69XoHs3Az7PineILyNwbDck9uU2jkaXnwxoCTa4qlK8bR-lEI9-VXPNdbCvfgb5H9wfYsJcw2CMzNxNhV8v9YVZEt90evylwtTCEpXq4T3zRCQvrpbCvZrXqJ8uvlFeqCsvvhlIkSfPhBY8nm2ocWtBGPZm58zLe5FMi1jept0B54U38ZxkZlrGQKar47jkmnc6gpLrkpDBp7cWz",
"token_type":"bearer",
"expires_in":1209599,
"userName":"joe",
".issued":"Fri, 01 Aug 2014 16:16:02 GMT",
".expires":"Fri, 15 Aug 2014 16:16:02 GMT"
}
What I want to find out is what format the access_token is in and what information is contained.
A clue I found was: you can choose what kind of tokens Web API uses by setting the OAuthAuthorizationServerOptions.AccessTokenFormat property in Startup.Auth.cs. The documentation for OAuthAuthorizationServerOptions says:
"The data format used to protect the information contained in the access token. If not provided by the application the default data protection provider depends on the host server. The SystemWeb host on IIS will use ASP.NET machine key data protection, and HttpListener and other self-hosted servers will use DPAPI data protection. If a different access token provider or format is assigned, a compatible instance must be assigned to the OAuthBearerAuthenticationOptions.AccessTokenProvider or OAuthBearerAuthenticationOptions.AccessTokenFormat property of the resource server."
So it's probably encoded using the MachineKey. That's fine, I can set the Machine Key OK but if I know the machine key that the token was created with, how do I decrypt it?
You are correct about the generation of the token. This token is an encrypted or signed string contains the de-serialized version of all the claims and ticket properties for the signed in user. If in IIS mode (SystemWeb), the encryption and signing is done via the "decryptionKey" and "validationKey" key values in machineKey node. If running as a self-host OWIN application, the encryption uses the DPAPI to protect it and that actually uses the 3DES algorithm.
To decrypt it you need to invoke this code in your API controller action method (not necessary but if you want to see what inside this encrypted token) :
string token = "Your token goes here";
Microsoft.Owin.Security.AuthenticationTicket ticket= Startup.OAuthBearerOptions.AccessTokenFormat.Unprotect(token);
If you need to configure your AuthZ server to issue JWT signed tokens so you can deconde them using someone line tool such as Google JWT decoder; then I recommend you to read my blog post here about JSON Web Token in ASP.NET Web API 2 using Owin
I've written a hosted Chrome Web App which authenticates the user with OAuth 2.0 using the Google APIs Client Library for .NET. Now I want to add payments to our application using the in-built Chrome Web Store Payments.
Looking at the documentation it appears that I need an OpenID URL in order to check for payment.
How can I get this UserID/OpenID URL since I'm using OAuth instead of OpenID authentication?
var service = new Google.Apis.Oauth2.v2.Oauth2Service(
new BaseClientService.Initializer
{
HttpClientInitializer = userCredential,
ApplicationName = "My App Name",
}
);
HttpResponseMessage message = await service.HttpClient.GetAsync(
string.Format("https://www.googleapis.com/chromewebstore/v1/licenses/{0}/{1}",
appId,
fedId // Where do I get this??
)
);
I wanted to leave my own experience here so that others can see that it's not just a matter of using the existing Id returned from an authorised request to the user profile endpoint, as this is not the ID required by the Chrome Payments API...
Short Answer
It's not possible to use only OAuth2.0 for a hosted app. The only options for a hosted app are:
Use the deprecated OpenID (see detailed answer)
Use In-app Payments using Google Wallet for Digital Goods
Long Answer
We still have to use OpenID, however Google has provided a migration path for OpenID users to OAuth2.0 called OpenID Connect. The aim of this migration is to map the old fedId field to new the Google+ User Ids.
This allows us to retrieve an OpenID identifier using an existing OAuth 2.0 process.
Caveat: The Google .NET Client APIs do not support this migration path. So authentication must be done manually or using a 3rd party OAuth library.
Howto:
As per usual OAuth flow, direct the user to the Authenticate endpoint (https://accounts.google.com/o/oauth2/auth) with the following variables:
openid.realm=http://localhost ** Required, where http://localhost matches your redirect_uri variable
scope=openid profile https://www.googleapis.com/auth/chromewebstore.readonly ** Both openid and profile scopes are required in order to retrieve the OpenID identifier. The chromewebstore scope is required to query the payments API.
Then exchange the code for an access token from the Token endpoint (https://accounts.google.com/o/oauth2/token)
At this point you will receive the standard access_token, refresh_token, etc variables but also an additional id_token variable.
This id_token is a JWT-encoded string containing the OpenID information.
Decoding this JWT-encoded (you can use this C# JWT Library) string will give you a JSON string in the following format:
{
"aud": "<googleuserid>.apps.googleusercontent.com",
"at_hash": "<hashcode>",
"iss": "accounts.google.com",
"openid_id": "<!! The fedId we require !!>",
"exp": <id>,
"azp": "<googleuserid>.apps.googleusercontent.com",
"iat": <id>,
"sub": "<googleuserid>"
}
At this stage we've finally found what we're looking for, the openid_id. This can be used to communicate with the Chrome Payments API
While still using the same OAuth credentials, make a signed request to the following URL:
https://www.googleapis.com/chromewebstore/v1/licenses/{appId}/{openId}
{appId} is the ID of your app within the Chrome Web Store
{openId} is the openid_id from the JWT response
This should give you what you need:
https://developers.google.com/accounts/docs/OAuth2
Its a complete overview of OAuth2.0.
Helped me with a problem I was having with a webapp setup, hope it can do the same.
P.S - Im not sure but this may be exactly what your looking for:
https://developers.google.com/accounts/docs/OAuth2InstalledApp
I have a basic SPA template with WebApi 2 backend that uses Microsoft account as external login provider. I also have a WP8 client in which users can login with their Microsoft account, both the SPA and WP8 client use ClientId so a users with same email address get the same identifiers in both clients (the ProviderKeys stored at the db match the id's for the same users when they log in on the phone).
When a user has logged in through the browser I can get their access_token and authenticate further requests they make against the api through the bearer token, this works well, returning 200 every time. On the WP8 client it doesnt work however, this is how I get the token:
LiveAuthClient Auth = new LiveAuthClient("0000000041422E16");
//some code removed
LiveConnectClient connect = new LiveConnectClient(Auth.Session);
string access_token = connect.Session.AccessToken;
//use token to send a http request to an authorized endpoint
I've used Fiddler to test the access token and the WebApi always return 401, what am I doing wrong here? Aren't the tokens sent back by the Live SDK client valid for authentication on the WebApi endpoints?