Oauth 2.0: I can't get profile info from Google "token info endpoint" by using id_token - authentication

I'm trying to get user info (profile,email) from Google by using OAuth 2.0.
But "token info endpoint" did not return profile info even though I set "profile" to scopes.
I followed the doc of Google sign-in for iOS. (https://developers.google.com/identity/sign-in/ios/backend-auth)
I couldn't figure out why this end point doesn't return profile info as I expected.
First I get Token by oauth2.0 (as a test, I got token using Rails)
def gmail
require 'oauth2'
client = OAuth2::Client.new(
'Client-id',
'client-secret',
{
site: 'https://accounts.google.com/',
authorize_url: 'o/oauth2/auth',
}
)
redirect_to client.auth_code.authorize_url(
redirect_uri: 'http://localhost:3000/google_signup',
scope: 'email profile',
)
end
token = client.auth_code.get_token(
params[:code],
redirect_uri: 'http://localhost:3000/gmail_signup',
and I get id_tokenfrom this token.
then, send GET request to "token info endpoint".
"https://www.googleapis.com/oauth2/v3/tokeninfo?id_token=id_token"
but response didn't contain profile info.
{
"azp": "azp",
"aud": "aud",
"sub": "sub",
"email": "email#gmail.com",
"email_verified": "true",
"at_hash": "at_hash",
"exp": "TIMESTAMP",
"iss": "accounts.google.com",
"iat": "iat",
"alg": "alg",
"kid": "kid"
}
The response was supposed to be like this.
{
// These six fields are included in all Google ID Tokens.
"iss": "https://accounts.google.com",
"sub": "110169484474386276334",
"azp": "1008719970978-hb24n2dstb40o45d4feuo2ukqmcc6381.apps.googleusercontent.com",
"aud": "1008719970978-hb24n2dstb40o45d4feuo2ukqmcc6381.apps.googleusercontent.com",
"iat": "1433978353",
"exp": "1433981953",
// These seven fields are only included when the user has granted the "profile" and
// "email" OAuth scopes to the application.
"email": "testuser#gmail.com",
"email_verified": "true",
"name" : "Test User",
"picture": "https://lh4.googleusercontent.com/-kYgzyAWpZzJ/ABCDEFGHI/AAAJKLMNOP/tIXL9Ir44LE/s99-c/photo.jpg",
"given_name": "Test",
"family_name": "User",
"locale": "en"
}

Related

Microsoft Graph API - 401 Unauthorized While Creating Chat

I using the graph API v1.0 to create the one-to-One chat,but I found some account get 401 results.I check the Permission from the Api '/me/oauth2PermissionGrants',and I can find the 'Chat.Create' permission.
{
"#odata.context": "https://graph.microsoft.com/v1.0/$metadata#oauth2PermissionGrants",
"value": [
{
"clientId": "9fc4855b-4d7e-443b-a8f0-282690a55a73",
"consentType": "Principal",
"id": "W4XEn35NO0So8CgmkKVacwsSh1fUKDpBhq1AxEmfwg74z92MWfk9ToJPj-kyp8I8",
"principalId": "8cddcff8-f959-4e3d-824f-8fe932a7c23c",
"resourceId": "5787120b-28d4-413a-86ad-40c4499fc20e",
"scope": " offline_access openid profile email User.Read User.ReadWrite User.ReadBasic.All Chat.ReadWrite Chat.Create Presence.Read Presence.Read.All ChatMessage.Read ChatMessage.Send"
},
{
"clientId": "d39356e1-6d20-4d19-ad54-5278e19b94ec",
"consentType": "Principal",
"id": "4VaT0yBtGU2tVFJ44ZuU7AsSh1fUKDpBhq1AxEmfwg74z92MWfk9ToJPj-kyp8I8",
"principalId": "8cddcff8-f959-4e3d-824f-8fe932a7c23c",
"resourceId": "5787120b-28d4-413a-86ad-40c4499fc20e",
"scope": " offline_access openid profile email User.Read User.ReadWrite User.ReadBasic.All Chat.ReadWrite Chat.Create Presence.Read Presence.Read.All ChatMessage.Read ChatMessage.Send"
},
{
"clientId": "c81831d1-608e-43fa-abd4-3a09e523cb3c",
"consentType": "Principal",
"id": "0TEYyI5g-kOr1DoJ5SPLPAsSh1fUKDpBhq1AxEmfwg74z92MWfk9ToJPj-kyp8I8",
"principalId": "8cddcff8-f959-4e3d-824f-8fe932a7c23c",
"resourceId": "5787120b-28d4-413a-86ad-40c4499fc20e",
"scope": " offline_access openid profile email User.Read User.ReadWrite User.ReadBasic.All Chat.ReadWrite Chat.Create Presence.Read Presence.Read.All ChatMessage.Read ChatMessage.Send Files.Read Files.ReadWrite Files.Read.All Files.ReadWrite.All Sites.Read.All Sites.ReadWrite.All"
}
]
}
When I post "https://graph.microsoft.com/v1.0/chats",
set the body like this
{"members":[
{ "user#odata.bind":"https://graph.microsoft.com/v1.0/users('8cddcff8-f959-4e3d-824f-8fe932a7c23c')",
"#odata.type":"#microsoft.graph.aadUserConversationMember",
"roles":["owner"]},
{ "user#odata.bind":"https://graph.microsoft.com/v1.0/users('636f150e-f73c-44d6-be0c-4d543b2b4e5d')",
"#odata.type":"#microsoft.graph.aadUserConversationMember",
"roles":["owner"]
}
],
"chatType":"oneOnOne"
}
It response 401 Authentication failed
{
"error": {
"code": "Unauthorized",
"message": "Authentication failed.",
"innerError": {
"date": "2022-05-17T08:41:05",
"request-id": "de03512e-b97d-4229-b1ce-a73a61ed4f3d",
"client-request-id": "de03512e-b97d-4229-b1ce-a73a61ed4f3d"
}
}
}
When I replace another account's token & teamsUserId and try again ,It returns Ok!
Can you help me check the reason?
First of all check your app id secret and confirm
secondly check that the users you are trying to add have authorized your application.
thirdly check for access token you need scopes and permission according to the token you are sending to the graph
If you are using application token , use default scope and check whether you have added the chat.create application permission else if you are using token on behalf of user you need delegated permission for chat.create application

Question about ASP.NET Core 3 Identity / Identity Server / SPA support for Resource Owner Password Grant Type

As per Authentication and authorization for SPAs, I have created a new SPA with support for API authorization. You can view this on GitHub.
In order to support integration tests, I have added a new client (see appsettings.json) that is allowed the resource owner password grant type:
"SecureSpa.IntegrationTests": {
"Profile": "IdentityServerSPA",
"AllowedGrantTypes": [ "password" ],
"ClientSecrets": [ { "Value": "K7gNU3sdo+OL0wNhqoVWhr3g6s1xYv72ol/pe/Unols=" } ],
"AllowedScopes": [ "SecureSpaAPI", "openid", "profile" ]
}
Then within WeatherForecastControllerTests.cs, I attempt to request the token as follows:
var response = await client.RequestPasswordTokenAsync(new PasswordTokenRequest
{
Address = disco.TokenEndpoint,
ClientId = "SecureSpa.IntegrationTests",
ClientSecret = "secret",
Scope = "SecureSpaAPI openid profile",
UserName = "demouser#securespa",
Password = "Pass#word1"
});
When running the test, I've tried many different combinations, however the results are usually the same (unauthorized_client). This is the relevant log output from Identity Server:
IdentityServer4.Endpoints.TokenEndpoint: Debug: Start token request.
IdentityServer4.Validation.ClientSecretValidator: Debug: Start client validation
IdentityServer4.Validation.BasicAuthenticationSecretParser: Debug: Start parsing Basic Authentication secret
IdentityServer4.Validation.PostBodySecretParser: Debug: Start parsing for secret in post body
IdentityServer4.Validation.SecretParser: Debug: Parser found secret: PostBodySecretParser
IdentityServer4.Validation.SecretParser: Debug: Secret id found: SecureSpa.IntegrationTests
IdentityServer4.Stores.ValidatingClientStore: Debug: client configuration validation for client SecureSpa.IntegrationTests succeeded.
IdentityServer4.Validation.ClientSecretValidator: Debug: Public Client - skipping secret validation success
IdentityServer4.Validation.ClientSecretValidator: Debug: Client validation success
IdentityServer4.Events.DefaultEventService: Information: {
"Name": "Client Authentication Success",
"Category": "Authentication",
"EventType": "Success",
"Id": 1010,
"ClientId": "SecureSpa.IntegrationTests",
"AuthenticationMethod": "SharedSecret",
"ActivityId": "0HLPN4PPDDMCJ",
"TimeStamp": "2019-09-12T02:10:57Z",
"ProcessId": 28948,
"LocalIpAddress": "unknown",
"RemoteIpAddress": "unknown"
}
IdentityServer4.Validation.TokenRequestValidator: Debug: Start token request validation
IdentityServer4.Validation.TokenRequestValidator: Debug: Start resource owner password token request validation
IdentityServer4.Validation.TokenRequestValidator: Error: Client not authorized for resource owner flow, check the AllowedGrantTypes setting{ client_id = SecureSpa.IntegrationTests }, details: {
"ClientId": "SecureSpa.IntegrationTests",
"ClientName": "SecureSpa.IntegrationTests",
"GrantType": "password",
"Raw": {
"grant_type": "password",
"username": "demouser#securespa",
"password": "***REDACTED***",
"scope": "SecureSpaAPI",
"client_id": "SecureSpa.IntegrationTests",
"client_secret": "***REDACTED***"
}
}
IdentityServer4.Events.DefaultEventService: Information: {
"Name": "Token Issued Failure",
"Category": "Token",
"EventType": "Failure",
"Id": 2001,
"ClientId": "SecureSpa.IntegrationTests",
"ClientName": "SecureSpa.IntegrationTests",
"Endpoint": "Token",
"GrantType": "password",
"Error": "unauthorized_client",
"ActivityId": "0HLPN4PPDDMCJ",
"TimeStamp": "2019-09-12T02:10:57Z",
"ProcessId": 28948,
"LocalIpAddress": "unknown",
"RemoteIpAddress": "unknown"
}
Microsoft.AspNetCore.Hosting.Diagnostics: Information: Request finished in 212.96790000000001ms 400 application/json; charset=UTF-8
Is this approach supported? If not, is there an alternative approach that can be used to get the token in order to write integration tests? I'm planning to set up test users along with the test client so that I can test lots of different behaviours.
I continued working on this issue and found that the allowed grant type of password was not being added when the profile is set to IdentityServerSPA. I couldn't see a way to add a client without a profile via appsettings, so I removed the configuration from appsettings and created the clients using this approach:
services.AddIdentityServer()
//.AddApiAuthorization<ApplicationUser, ApplicationDbContext>();
.AddApiAuthorization<ApplicationUser, ApplicationDbContext>(options =>
{
options.Clients.AddIdentityServerSPA("SecureSpa", builder =>
{
builder.WithRedirectUri("https://localhost:44307/authentication/login-callback");
builder.WithLogoutRedirectUri("https://localhost:44307/authentication/logout-callback");
});
options.Clients.Add(new Client
{
ClientId = "SecureSpa.IntegrationTests",
AllowedGrantTypes = { GrantType.ResourceOwnerPassword },
ClientSecrets = { new Secret("secret".Sha256()) },
AllowedScopes = { "SecureSpaAPI", "openid", "profile" }
});
});
With that in place my tests now run. You can see the final solution here; https://github.com/JasonGT/SecureSpa/.
Everything works fine, however there seems to be a bug (or feature limitation) within DefaultClientRequestParametersProvider. See the 'GetClientParameters' method - if the specified client does not have an associated profile, an InvalidOperationException is thrown.
Let me know if you need more information.
Just for reference' sake: the code above did not work as-is on my end, it broke the SPA sign-in with a redirect_uri invalid exception.
I had to remove the base url, and then it worked:
builder.WithRedirectUri("/authentication/login-callback");
builder.WithLogoutRedirectUri("/authentication/logout-callback");

use react-native-google-signin with custom domain

I have google signin in a web and a react native app (android and ios).
I can login in both platforms but the token data differs (and because of that the app's one is invalid)
I've looked the docs and try multiple params in different fields but no success
app configuration:
// scopes: ['profile', 'email'], // it doesn't matter if commented or not
// webClientId: '**********.apps.googleusercontent.com', //
// offlineAccess: false, // if you want to access Google API on behalf of the user FROM YOUR SERVER
// hostedDomain: 'https://securetoken.google.com/**********', // if I use this, (or other strings I tried, cant login
// loginHint: '',
forceConsentPrompt: true,
accountName: '**********', //
// accountName: '**********:android:**********', // nothing happens
iosClientId: '**********.apps.googleusercontent.com', // is different from the android one
web configuration (with firebase):
apiKey: "**********",
authDomain: "**********.firebaseapp.com",
databaseURL: "https://**********.firebaseio.com",
projectId: "**********",
storageBucket: "",
2: "**********",
appId: "**********:web:**********"
web token infromation:
{
"iss": "https://securetoken.google.com/**********",
"aud": "**********",
"sub": "**********",
"email": "**********#gmail.com",
"email_verified": true,
"name": "**********",
"picture": "**********",
"auth_time": 1568973313,
"user_id": "**********",
"sign_in_provider": "google.com",
"iat": **********,
"exp": **********,
"firebase": {
"identities": {
"google.com": ["**********"],
"email": ["**********#gmail.com"]
}
}
}
app token information:
{
"iss": "https://accounts.google.com",
"azp": "**********.apps.googleusercontent.com",
"aud": "**********.apps.googleusercontent.com",
"sub": "**********",
"email": "**********#gmail.com",
"email_verified": true,
"name": "**********",
"picture": **********",
"given_name": "**********",
"family_name": "**********",
"locale": "es",
"iat": **********,
"exp": **********
}
I manage to solve it using also firebase (firebase.initializeApp(/params/)) , first I do a login with react-native-google-signin and then, if success, login with firebase to obtain the correct token:
// login with google, on web is unnecesary, to use native interface
const { user } = await GoogleSignin.signIn();
const googleTokens = await GoogleSignin.getTokens();
// login with firebase, to get the correct token
const credential = firebase.auth.GoogleAuthProvider.credential(googleTokens.idToken, googleTokens.accessToken);
const auth = firebase.auth();
await auth.signInWithCredential(credential);
// get firebase token and user email
const idToken = auth.currentUser && (await auth.currentUser.getIdToken(true));
const email = user && user.email;
// login into my back
if (idToken && email) googleLogIn(email, idToken);

Auth.currentAuthenticatedUser not loading name and family name attributes (and others) from Cognito

I'm using the Auth.currentAuthenticatedUser method to retrieve the attributes recorded for the logged user from AWS Cognito - but only basic atributes are showing. The ones I want are "name" and "family name", but they don't seem to be loaded in the Promise.
This is only the beggining, but I'm concerned as I will want to retrieve other attributes which are not showing up, like user picture, for instance.
Tried to use currentAuthenticatedUser and currentUserInfo with the same results.
async componentDidMount() {
await Auth.currentAuthenticatedUser({bypassCache: true})
.then ( user => this.setUserInfo( user ) )
.catch( err => console.log(err))
}
CognitoUser {
"Session": null,
"attributes": Object {
"email": "r...#gmail.com",
"email_verified": true,
"phone_number": "+5...",
"phone_number_verified": false,
"sub": "246e9...",
},
"authenticationFlowType": "USER_SRP_AUTH",
"client": Client {
"endpoint": "https://cognito-idp.us-east-2.amazonaws.com/",
"userAgent": "aws-amplify/0.1.x react-native",
},
"deviceKey": undefined,
"keyPrefix": "CognitoIdentityServiceProvider.12ddetjn0c0jo0npi6lrec63a7",
"pool": CognitoUserPool {
"advancedSecurityDataCollectionFlag": true,
"client": Client {
"endpoint": "https://cognito-idp.us-east-2.amazonaws.com/",
"userAgent": "aws-amplify/0.1.x react-native",
},
"clientId": "12ddetjn0c0jo0npi6lrec63a7",
"storage": [Function MemoryStorage],
"userPoolId": "us-east...",
},
"preferredMFA": "NOMFA",
"signInUserSession": CognitoUserSession {
"accessToken": CognitoAccessToken {
"jwtToken": "e...oJPg",
"payload": Object {
"auth_time": 1565137817,
"client_id": "1...6lrec63a7",
"event_id": "c3...-4bd9-ad42-200f95f9921c",
"exp": 15...2,
"iat": 156...5872,
"iss": "https://cognito-idp.us-east-2.amazonaws.com/us-east-...",
"jti": "5483e...544149c42e58",
"scope": "aws.cognito.signin.user.admin",
"sub": "246e93...f4d8e6f4725b",
"token_use": "access",
"username": "r...f",
},
},
"clockDrift": -2,
"idToken": CognitoIdToken {
"jwtToken": "eyJraWQiOiJk...",
"payload": Object {
"aud": "12ddetjn0c0j..rec63a7",
"auth_time": 1565137817,
"cognito:username": "r..",
"email": "r..#gmail.com",
"email_verified": true,
"event_id": "c3ae..200f95f9921c",
"exp": ..2,
"iat": ..2,
"iss": "https://cognito-idp.us-east-2.amazonaws.com/us-east-..",
"phone_number": "+5...3",
"phone_number_verified": false,
"sub": "246e937..f4d8e6f4725b",
"token_use": "id",
},
},
"refreshToken": CognitoRefreshToken {
"token": "eyJjd...",
},
},
"storage": [Function MemoryStorage],
"userDataKey": "CognitoIdentityServiceProvider.12ddetjn0....userData",
"username": "r...ff",
}
To get all user attributes, you may be looking for the Auth.userAttributes() function. To use this you want something like this code:
const authUser = await Auth.currentAuthenticatedUser();
const attributes = await Auth.userAttributes(authUser);
// the next line is a convenience that moves the attributes into
// the authUser object
attributes.forEach((attr) => {
authUser.attributes[attr.Name] = attr.Value;
});
If you're still not getting the attributes you need, take a look here, and you can see that you can enable the reading of other attributes from the Amplify command line.
So, in the root of your project:
Type "amplify update auth" at the console.
Select "Walkthrough the auth configurations"
Step through making all the same selections as you've done before.
When it asks, "Do you want to specify the user attributes this app can read and write?" it's "Y", and then you select the attributes you want to be able to read.
When you finish the wizard, use "amplify push auth"
When that's completed, try re-running.
As an alternative to steps 1-4 above, you can also edit cli-inputs.json in the amplify\backend\auth<your auth config name> directory. It's in "userpoolClientReadAttributes". Simply add the attributes you would like to this array (e.g. "name").
This answer was verified with amplify CLI version 8.1.0.

Identity Manager throws 401 unauthorized

I am using following configuration for my Identity Manager, everytime I pass my access token - it throws 401 (Unauthorized)
app.Map("/admin", adminApp =>
{
var factory = new IdentityManagerServiceFactory();
factory.ConfigureSimpleIdentityManagerService("AspId");
var securityConfig = new ExternalBearerTokenConfiguration
{
Issuer = "https://localhost:44333/core",
Audience = "https://localhost:44333/core/resources",
Scope = "idmgr",
SigningCert = Certificate.Get(),
};
adminApp.UseIdentityManager(new IdentityManagerOptions()
{
Factory = factory,
SecurityConfiguration = securityConfig
});
});
My acesss token which I pass as AUthorization Bearer looks like
{
"iss": "https://localhost:44333/core",
"aud": "https://localhost:44333/core/resources",
"exp": 1449995870,
"nbf": 1449995510,
"client_id": "roclient",
"scope": [
"email",
"idmgr",
"openid",
"phone",
"profile"
],
"sub": "58067d52-64bf-4447-a928-d3a1316bd677",
"auth_time": 1449995509,
"idp": "idsrv",
"role": [
"admin",
"IdentityManagerAdministrator"
],
"amr": [
"password"
]
}
Is it something I am not doing right ?