I try to implement a SSO mechanism with SAM2 bearer oAuth over WSO2.
1. User call WebAPP1
2. WebAPP1 (SP) redirect the user on the IDP login Page (OpenAM)
3. WebAPP1 (SP) call oAuth server (WSO2 IS or AM) with SAML2 to get oAuth token
At this step WSO2 IS (or AM) fails with the error : "SAML assertion audience verification failed".
I don't understand why because the audience value set in my SAML2 sent to oAuth server is the same as defined in the "Trusted Identity Provider" on IS or AM.
I don't understand why ... please help me !
Nicolas
I guess SAML assertion may not contain the all audience urls. In Trusted IDP UI, you can configure identity provider audiences. If you have defined them, those urls must be in the assertion. Also.. value that is defined by "OAuth2 Token Endpoint Name:" must be also as an audience url in assertion.
Related
I've spent the last couple days trying to set up Cognito to use Battle.net OIDC. I believe I am most of the way there. I can see using the cognito hosted UI that it authenticates correctly but then fails, presumably trying to retrieve the token.
The first request to cognito hosted UI:
https://<removed>.auth.us-west-2.amazoncognito.com/oauth2/authorize?identity_provider=Blizzard&redirect_uri=https://<my-site-oauth-handler-removed>/oauth&response_type=CODE&client_id=<removed>&scope=openid
Then the next request is to Battle.net OIDC as expected:
https://us.battle.net/oauth/authorize?client_id=<removed>&redirect_uri=https%3A%2F%2F<removed>.auth.us-west-2.amazoncognito.com%2Foauth2%2Fidpresponse&scope=openid&response_type=code&state=<removed>
Then the code is passed onto the cognito idpresponse:
https://<removed>.auth.us-west-2.amazoncognito.com/oauth2/idpresponse?code=<removed>&state=<removed>
At this point, if my understanding is correct cognito should try to hit the battle.net /oath/token endpoint and then return the id_token and access_token to my redirect_url. It is at the point cognito instead returns an error to my url:
https://<my-site-oauth-handler-removed>/oauth?error_description=Bad+id_token+issuer+oauth.battle.net&error=invalid_request
Judging by the lack of documentation for Battle.net OIDC I may be one of a handful trying to use the battle.net OIDC with Cognito. It very well could be a bug with their implementation but I'm trying not to jump to that conclusion.
My best guess right now is that I haven't configured Cognito correctly to make the token POST request. It needs to use Basic Authentication with the clientid:password but I can't verify if it's doing that correctly or not since its abstracted away.
Anyway, when I make the request through my app (using amplify to open the hosted UI) it does return but with the following:
[ERROR] 51:05.25 OAuth - Error handling auth response. Error: Bad+id_token+issuer+oauth.battle.net
at OAuth.<anonymous> (OAuth.js:202)
at step (OAuth.js:52)
at Object.next (OAuth.js:33)
at OAuth.js:27
at tryCallTwo (core.js:45)
at doResolve (core.js:200)
at new Promise (core.js:66)
at __awaiter (OAuth.js:23)
at OAuth.handleAuthResponse (OAuth.js:181)
at AuthClass.<anonymous> (Auth.js:1632)
Here is all my relevant Cognito configuration:
OIDC Provider:
Provider Name: Blizzard
Client ID: [removed]
Client Secret: [removed]
Attributes request method: POST
Authorize scope: openid
Issuer: https://us.battle.net/oauth
App Client:
Name: [removed]
App client id: [removed]
App client secret: (no secret key)
App Client Settings:
Enabled Identity Providers: Blizzard
Callback URLs: https://[removed]/oauth
Sign out URLs: https://[removed]/oauth
Allowed OAuth Flows:
Authorization code grant
Implicit grant
Allowed OAuth Scopes
email
openid
aws.cognito.signin.user.admin
profile
(I've tried every variation of these and it doesn't appear to change the outcome)
Federated Identity:
Authentication providers
OpenID
us.battle.net/oauth
IAM Identity Providers:
Provider Name: us.battle.net/oauth
Provider Type: OIDC
Provider URL: us.battle.net/oauth
CA Thumbprint: [removed]
Audience: [my battle.net client id]
I have exhausted my own resources and am asking for any guidance with this.
Thanks!
This was caused by Blizzard issuing their tokens from their well-known endpoints but setting the iss field to oauth.battle.net which caused Cognito (or any other token validation) to fail hence the error message
Bad+id_token+issuer+oauth.battle.net
I brought this up to their API team in Discord and they are releasing a fix on November 25th according to an email send to developers.
Dear community developer,
Earlier this year, we introduced a new OAuth discovery endpoint which
implements the OpenID Connect discovery specification. We would like
to deploy a change to the issuer field iss of the id_token during the
OpenID authorization flow from oauth.battle.net to the issuer that is
returned by the well-known configuration endpoint JSON response. This
would be a potential breaking change to some of the OAuth OIDC clients
but it conforms to the OpenID connect specification:
https://openid.net/specs/openid-connect-core-1_0.html#IssuerIdentifier
Your OAuth client application was identified as one that could be
affected by this change.
We are planning to release this change on November 25, 2019.
Here are the steps that you can take to ensure your OpenID Connect
client will continue working after the change:
Navigate to one of the well-known configuration endpoints below which
corresponds to the region where your client application operates and
check the "issuer" field.
If the issuer field matches the configured issuer for your OAuth OIDC
client then your client is compatible and you are already compliant
and do not need to make any changes.
If the issuer field from the well-known configuration endpoint is
different than the issuer set in your client configuration, please
change the issuer to match the well-known configuration endpoint.
If your client supports the OpenID discovery endpoint standard, you
can configure it to read all necessary settings from the well-known
configuration endpoint. Your OAuth client should self-configure.
Implementing SSO in my application and from app-1 i need to make a rest call to app-2. Login in app-1 with SAML and authenticated successfully and trying for rest call from app-1 with openid but since authentication is using saml only so not able to get the access/bearer token. Please help how to get the access/bearer token from saml request/response. I'm using Keycloak Server for SSO implementation.
You can't.
REST API need a JWT token not a SAML one.
Change SAML to OpenID Connect and it will work.
(1) OpenID Connect 1.0 is a simple identity layer on top of the OAuth 2.0 protocol. It allows Clients to verify the identity of the End-User based on the authentication performed by an Authorization Server, as well as to obtain basic profile information about the End-User in an interoperable and REST-like manner.
(2) Presently there is no IETF draft document regarding SAML 2.0 Profile for OpenID Connect client.
We can refer to the IETF draft document SAML 2.0 Profile for OAuth 2.0 client.
The OAuth 2.0 Access Token using SAML Assertion filter enables an OAuth client to request an access token using a SAML assertion. This supports the OAuth 2.0 SAML flow, which is used when a client wishes to utilize an existing trust relationship, expressed through the semantics of the SAML assertion, without a direct user approval step at the authorization server. For more details on supported OAuth flows, see API Gateway OAuth 2.0 authentication flows.
(3) Both Auth0 and open-source WSO2 Identity Server implement the SAML profile for OpenID Connect/OAuth to convert SAML token to OpenID Connect/OAuth token, as demonstrated by Auth0 SAML Configuration and WSO2 Adding and Configuring an Identity Provider. In other words, Auth0 and WSO2 Identity Server can relay SAML authentication provided by SAML IdP to either OpenID Connect client or OAuth 2.0 client.
I want to use AWS cognito as a OpenId connect provider.My AWS cognito IDP will intern call my another OpenId provider to authenticate the user. It will then create its new token and hand over to callers as its own.
The OpenID provider used internally by AWS cognito pool is transparent to user. User only configures AWS cognito as its IDP provider.
User case
User authenticates with My AWS IDP provider
My IDP provider authenticates the user agains Googles IDP provider
My IDP decodes the token returned by Google IDP.
My IDP Creates new token and add additional claims.
My IDP hands over my JWT to user.
Question
Is this possible in AWS cognito?
Does AWS user pool expose OpenID connect endpoint?
Cognito does provide an OpenId connect endpoint, as detailed in this blog post by #Badri
The formula for the authority is:
https://cognito-idp.{region}.amazonaws.com/{userPoolId}
And you can verify by checking the metadata URL that something is there
https://cognito-idp.{region}.amazonaws.com/{userPoolId}/.well-known/openid-configuration
Then during client pool setup, you can federate with other OIDC providers, and also enable the OIDC provider in the app client settings. Which should enable your scenario which sounds very similar to what I would like to do. However, the blog post misses one crucial piece of configuration, which is setting a domain name for the app integration. This StackOverflow question shows the error you will receive if you do not configure this domain and links to the solution in an answer. Once I set the domain, Badri's code worked for me.
To give a more detailed answer on Cognito's OpenID Connect support.
Discovery Endpoint
Cognito exposes an OpenID Connect Discovery endpoint as described at https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationRequest at the following location:
https://cognito-idp.{region}.amazonaws.com/{userPoolId}/.well-known/openid-configuration
Response Types
The above endpoint returns the following three response_types:
"response_types_supported":["code","token","token id_token"]
code: defined in https://www.rfc-editor.org/rfc/rfc6749#section-11.3.2 - this worked for us, but only when a domain was specified as below.
token: this value is forbidden by OpenID Connect at https://openid.net/specs/openid-connect-core-1_0.html#ImplicitAuthRequest - "NOTE: While OAuth 2.0 also defines the token Response Type value for the Implicit Flow, OpenID Connect does not use this Response Type, since no ID Token would be returned." - OpenID Connect libraries will ignore this response.
token id_token: this value triggers a redirect to an error page with the code "invalid_request". There is no indication given as to what is invalid with the request. AWS technical support claim that only "code" and "token" are supported by authorize endpoint, it is however not clear why this response_type is advertised if not supported.
Domain
Cognito gives the option to specify a domain that will prefix the hostname of the Cognito endpoint.
Without a domain being specified, Cognito will advertise generic URLs at the OpenID Connect discovery endpoint such as https://cognito-idp.eu-west-2.amazonaws.com/{userPoolId}/authorize, but all attempts to log in at these URLs return the error message:
{"code":"BadRequest","message":"The server did not understand the operation that was requested.","type":"client"}
The error message does not indicate what is bad about the request, so this appears to be a bug in Cognito.
With a domain specified, Cognito will advertise URLs that include the domain prefix, and the response_type "code" returns a login page as expected.
Logout
OpenID Connect Session Management at https://openid.net/specs/openid-connect-session-1_0.html#RPLogout describes how an OpenID Connect logout must be initiated, and requires as per https://openid.net/specs/openid-connect-session-1_0.html#OPMetadata that the end_session_endpoint parameter be included in the discovery metadata.
In the case of Cognito end_session_endpoint is omitted from the metadata.
RP-Initiated Logout at https://openid.net/specs/openid-connect-session-1_0.html#RPLogout describes how the logout endpoint works. If an attempt is made to pass the logout endpoint manually to the OpenID Connect client implementation, logout fails as follows:
{"code":"BadRequest","message":"The server did not understand the operation that was requested.","type":"client"}
Again, the error message gives no indication of the error, however the description of the logout endpoint at https://docs.aws.amazon.com/cognito/latest/developerguide/logout-endpoint.html shows no compatibility with OpenID Connect.
While you can log into Cognito using OpenID Connect, there is no option to log out.
Cloudformation
Cognito Cloudformation support is incomplete, and affects OpenID Connect as follows:
There is no way to specify a domain using Cloudformation, and the domain is required for OpenID Connect to work.
The callback URL is required by OpenID Connect, but cannot be set using Cloudformation.
Summary
To access Cognito using OpenID Connect, ensure that a domain is specified, and use the response_type "code" only. OpenID Connect logout is not possible. Other options violate the OpenID Connect specification, or were released broken.
I'm having a little trouble following your use case, but I'll explain some points that might help.
You can use Cognito User Pools to authenticate users through Google, and then issue JWT tokens from the Cognito User Pool. See the Developer Guide.
Cognito User Pools is not currently a full OpenID identity provider, but that is on our roadmap. User Pools do support OAuth2.0 flows, and they do provide OpenID standard JWT tokens.
I have installed and configured JWT Grant Type in WSO2 IS 5.3.0 following this guide
Then I have configured a Service Provider enabling the OAuth/OpenID Connect Inbound Authenticator.
I am able from a javascript client to authenticate the user exploiting the Oauth 2 protocol with open-id scope obtaining a valid JWT token (JWTToken).
Finally I tried to make a POST request to https://****/oauth2/token?grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=JWTToken using a REST Client and setting Content-Type=application/x-www-form-urlencoded.
When I do the request the WSOIS Server asks for a username and a password. I am able to pass this step providing a valid clientId and clientSecret.
Unfortunately at this point the server dos not reply with an access token but with a 400 Bad Request and in the response body writes "{"error_description":"Error occurred while decoding public certificate of Identity Provider default for tenant domain carbon.super","error":"invalid_grant"}"
I can't understand if the problem is the JWT Token that I pass to the server or if there is some issues with the certificates. Any help please?
Okay. I think this should help you.
If you take the OpenID connect token you got from WSO2 Identity Server and put it in jwt.io you would see that the openID connect will have the "iss" (issuer) value of "https://localhost:9443/oauth2/token" (replace localhost with your hostname if you have set the hostname) which is the token endpoint of WSO2 Identity Server.
So when you use this token as a JWT Bearer grant, in order to validate the signature the grant handler tries to retrieve an IDP with the name given in the issuer(iss) field (ie. token endpoint of WSO2 Identity Server). As it fails to find any identity provider it retrieves the default identity provider (note this is a dummy IDP added for sake of backward compatibility) which doesn't have any certificate. (you can find this under $IS_HOME/repository/conf/identity/identity-providers/default.xml)
So there are two ways to fix this,
Change the issuer value of Identity Server so that it can fetch the certifcate of it's resident identity provider.
To do this,
Login to the management console,
Go to Identity Provider --> Resident --> Inbound Authentication Configuration --> OAuth2/OpenID Connect Configuration --> set the
'Identity Provider Entity Id' value as LOCAL
Create a new Identity Provider with the name equal issuer value of the OpenID connect token (ie. the token endpoint) and upload the public certificate that could be used to verify the OpenID connect token.
Personally, I prefer the first solution :)
Update:
You also need to do one more change,
In identity.xml (found under repository/conf/identity) uncomment the following lines
<Audiences>
<Audience>
${carbon.protocol}://${carbon.host}:${carbon.management.port}/oauth2/token
</Audience>
</Audiences>
This will make sure that the audience validation check will pass for the issued OpenID connect token when used as a JWT bearer grant. (ie. the JWT Grant handler will validate whether the token endpoint is one of the audiences in the provided grant)
Like the Kerberos tickets, is it possible to forward to another application:
a SAML assertion
an OAuth token
Thank you,
SAML Assertions: Yes, one such protocol is WS-Trust where the Security Token Service (STS) generates SAML assertions and they can be presented to an end service (i.e. relying party) that trusts the STS. Another is the "SAML 2.0 Bearer Assertion Profile" for OAuth - simply, the SAML grant type - in which you can present the SAML assertion (usually got through SAML Web SSO) to the OAuth endpoint and exchange it to an Access Token.
OAuth Tokens: I'm not sure about a standard use case for this.