get client_id during refresh_token in aadb2c IEF - identity-experience-framework

I have IEF signup_signin policy written and I am looking to get client_id during refresh_token. is it even possible ?

Related

Microsoft Graph Admin Consent Flow Doesn't Contain Refresh Token

Is it possible to get refresh token also in the admin consent flow?
I've received access_token but not refresh_token even though I've included the offline_access permission in the delegated permissions.
to be more clear: I need to get to the users drive files (i.e get/update files) of the entire tenant (organization). therefore i'm requesting Application Permissions and Using the admin consent endpoint.
therefore I use the client_credentials grant in order to get the entire tenant access_token but unfortunately with no refresh_token in order to extend time of privileges of the tenant for more then 1 hour.
if i misuse the protocols above clarification will be highly appreciated
While Marc's answer is correct, I think the whole thing can be explained in a little more detail:
To get full access to a tenant (i.e. not just resources associated with the current consenting user), then you need to use the Admin Consent flow. However, unlike other flows in Graph's OAuth, you do not require a refresh_token to maintain access. Instead, you can simply request an access_token at any time once an admin has consented. Each access_token lasts 60 minutes.
Having first used other flows such as the Management API and Graph's Code Grant flow, this one confused me, but it's actually even simpler than those.
To get consent, simply direct the admin to the following URL:
https://login.microsoftonline.com/[Their Tenant ID]/adminconsent?client_id=[Your Client ID]&redirect_uri=[Your Redirect URI]
Your redirect URI will get a response with params:
?admin_consent=True&tenant=[Their Tenant ID]
Once you've received this confirmation, you can request an access_token at any time by sending a POST request with the following form fields:
client_id: [Your Client ID],
client_secret: [Your Client Secret],
scope: 'https://graph.microsoft.com/.default',
grant_type: 'client_credentials'
To the following URI:
https://login.microsoftonline.com/[Their Tenant ID]/oauth2/v2.0/token
The response will contain a new 60 minute access_token and you can simply call it again whenever required.
Refresh Tokens are only returned when both offline_access is requested and you are using the Authorization Code Grant.
More importantly, if you are receiving an access_token then you are not executing the Admin Consent workflow. Administrative Consent is only used for consenting to your application's scopes. The Admin Consent response does not contain an access_token, it only contains the Tenant ID (for the tenant that was consented) and a boolean that tells you if consent was granted as query parameters:
http://{return_uri}/?tenant=[tenant id]&admin_consent=[True/False]
If you are receiving an access_token then you are using either the Authorization Code, Client Credentials, or Implicit grants.
UPDATE:
There is no refresh token issued for Client Credentials, you simply request a new token from the /token endpoint as needed.

AADSTS50013: Assertion audience claim does not match the required value

I've got a single page app that authenticates users in Azure using adal-angular.js/adal.js [client].
The returned token is inserted into the auth header and passed to a web API [server]. This web api generates a new access token for the app using the on-behalf-of workflow (https://github.com/Azure-Samples/active-directory-dotnet-webapi-onbehalfof)
This token is then used to call a downstream API [API1].
So the downstream API then repeats this process to get a new token to call another API [API2]. It's at this point that I'm getting the above error.
The aud value in the token passed from [client] to [server] is the application id of the [server] app.
The aud value in the token passed from the [server] to [API1] is the Application URI of the [API1] app.
So far so good.
When I call AcquireTokenAsync in [API1] app, I get the following error:
AADSTS70002: Error validating credentials. AADSTS50013: Assertion audience claim does not match the required value. The audience in the assertion was 'http://application_uri.com/' and the expected audience is 'snip-a1d5-e82e84f4e19e' or one of the Application Uris of this application with App ID 'snip-a1d5-e82e84f4e19e'
The relevant code from [API1]:
public static async Task<string> GetApplicationTokenOnBehalfOfUser(string appId, string appKey)
{
var clientCredential = new ClientCredential(appId, appKey);
var bootstrapContext = ClaimsPrincipal.Current.Identities.First().BootstrapContext as
System.IdentityModel.Tokens.BootstrapContext;
var userName = ClaimsPrincipal.Current.FindFirst(ClaimTypes.Upn) != null ? ClaimsPrincipal.Current.FindFirst(ClaimTypes.Upn).Value : ClaimsPrincipal.Current.FindFirst(ClaimTypes.Email).Value;
var userAccessToken = bootstrapContext.Token;
var userAssertion = new UserAssertion(userAccessToken, _assertionType, userName);
var authority = string.Format(System.Globalization.CultureInfo.InvariantCulture, _aadInstance, _tenant);
var userId = ClaimsPrincipal.Current.FindFirst(ClaimTypes.NameIdentifier).Value;
var authContext = new AuthenticationContext(authority, new TokenCache());
var result = await authContext.AcquireTokenAsync(_resourceId, clientCredential, userAssertion);
var accessToken = result.AccessToken;
return accessToken;
}
Where:
appId = "snip-a1d5-e82e84f4e19e"
And the "aud" value from the BootstrapContext.Token is:
"aud": "http://application_uri.com/"
If I change the above to use the "aud" value from the token as the appId in the ClientCredential, I get this error instead:
AADSTS65001: The user or administrator has not consented to use the application with ID 'http://application_uri.com/'. Send an interactive authorization request for this user and resource.
Am I doing this right?
Thanks.
AADSTS70002: Error validating credentials. AADSTS50013: Assertion audience claim does not match the required value. The audience in the assertion was 'http://application_uri.com/' and the expected audience is 'snip-a1d5-e82e84f4e19e' or one of the Application Uris of this application with App ID 'snip-a1d5-e82e84f4e19e'
To use the on-behalf-of flow, we need to provide the access token for the API1 and provide the clientId and secrect of API1 to request the access token for the API2.
AADSTS65001: The user or administrator has not consented to use the application with ID 'http://application_uri.com/'. Send an interactive authorization request for this user and resource.
Before that tenant users can use the app, the corresponding service principal must be register to that tenant first by permission grant. Is API2 is not in the tenant of the users sign-in?
If I understand correctly, we need to specify the knownClientApplications in the manifest of API1(http://application_uri.com/') with the client_id of your SPA, and it also require to set the permission of API1 to the SPA. After that, when the users sign-in your SPA, the API1 app will also register to the users' tenant.
More detail about multi-tier applications please refer the document below:
How to sign in any Azure Active Directory (AD) user using the multi-tenant application pattern
Update( append the test result to explain)
To get this working I had to add the following delegated permissions to API1 for AP2.
Azure Permissions

IdentityServer4: Using refresh_token to get a new access_token when clients doesn't know the client_secret

Firstly: I can successfully make calls to
http://localhost:7791/connect/token POST
grant_type=refresh_token
&refresh_token={refresh_token}
&client_id=resource-owner-client
&client_secret=secret
and this returns a new access_token, refresh_token, expires_in, and token_type.
However, I want to do it without a client_secret.
In my case my clients are remote applications that have been issued a starting access_token, refresh_token, etc.
using this call.
http://localhost:7791/connect/token POST
grant_type=password
&scope=arbitrary offline_access
&client_id=resource-owner-client
&client_secret=secret&username=rat&password=poison
The initial call is trusted and the secrets know, but downstream usage of the refresh_token should not require the client_secret.
How can I configure this or where would I have to code my own abstraction to make things work this way?
Not out of the box.
You could implement that using an extension grant.
https://identityserver4.readthedocs.io/en/release/topics/extension_grants.html

AAD token: Why aud sometimes shows app id, sometimes it's the app url?

I'm using adal.js for my website for AAD authentication.
After decode the AAD token, the aud looks differently, it's the app api in AAD.
However, when I try to understand how AAD works in different scenarios, almost all the documentation's example of AAD token shows aud as the resource url, like http://contoso.com/.
Based on my understanding, aud means this token is issued for. There's no restriction to what it should actually be.
But I'm curious what's the main reason of this inconsistent behavior of aud from AAD.
Why it can be app id sometimes, and be a url sometimes?
Why not app id all the time or url all the time?
Could someone help to share some thoughts?
Thanks.
The "AUD" value in the token should match whatever the "Resource" value in the token request is. If you request a token where you specify the resource as an App ID, then you will get an AUD value with a GUID. Otherwise, if you use an App ID URI, you will get the URL back.
As a resource developer, it is important that you program your API so that you accept both forms of tokens, as they should both be valid to access your resource. I believe OWIN already takes care of this for you.
Let me know if this helps!
ADAL.JS deals with 2 types of tokens: id_token and access_token. id_token represents an identity of the user who has signed-in within your application. Very roughly it contains just 2 pieces - the ID of the user who provided the credentials and the ID of the application which acquired the token. In case of id_token the value of aud is Guid and corresponds to the AppId of the application acquired the token. From OAUTH v2 point of view this is the same application which contains resources the user wants to access.
Speaking of access_token - it represents not only those 2 mentioned above, the user and the acquiring application, but also an application with a set of resources the user is intended to access. This 2nd application, represented by aud claim, in majority of cases, will be a Uri which represents Service Principal Name (or App ID Uri or IdentifierUri) - all of those are synonyms. This value is a way to point from a Client AAD App to a Server AAD App - the one containing protected resources.
So, ADAL.JS first asks for a user's credentials and acquires an id_token and then it is sending additional request to AAD endpoint to get access_token. If you look into both of those tokens you will see different kind of value in the aud claim as explained above.
It is also possible to have a Guid in the aud claim for access_tokens - that Guid will correspond to the AppId of the resource application, so, if you have a code which parses the value it must be ready to process not only Uris but also Guids.

How to return refresh token on custom redirect?

I'm newcomer at gmail api. I'm already try to sendback refresh token and set approval_prompt = force when generate auth_url to get access_token but I'm still get only
{
"access_token" : "xxxxxxxxxxxxxxxxxxxxxxx",
"token_type" : "Bearer",
"expires_in" : 3600
}
Not have refresh_token
Can someone help me please ? Thank you so much for coming
Based on the Handling OAuth2.0 Response section of the Google Identity documentation, refresh_token will only be returned if the the access_type is offline.
refresh_token A token that may be used to obtain a new access token. Refresh tokens are valid until the user revokes access. This field is only present if access_type=offline is included in the authorization code request.

Resources