WSO2 id_token with missing claims - wso2

In my requirement, I need to get the "auth_time" and "acr" openid claim. On my id token only can get these claims:
amr, iss, exp, iat, nonce, c_hash, aud and at_hash
How can add these claims in token response?
I use openid-client node js library adding in scope="openid"

According to the OpenID Connect spec, auth_time and acr are optional claims. So by default WSO2 Identity server does not send these claims in id_token.
1. auth_time:
According to the spec,
auth_time: Time when the End-User authentication occurred. Its value is a JSON
number representing the number of seconds from 1970-01-01T0:0:0Z as
measured in UTC until the date/time. When a max_age request is made or
when auth_time is requested as an Essential Claim, then this Claim is
REQUIRED; otherwise, its inclusion is OPTIONAL.
Identity server adheres to the spec and you have options to get auth_time as a claim in the id_token.
Option1:
To get auth_time, you can send a request with max_time as a parameter during the authorization flow. A sample request is given below
https://localhost:9443/oauth2/authorize?response_type=code&scope=openid&max_age=12345&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2Fplayground2%2Foauth2client&client_id=KmerETRbZx2ErGhCqRfv4xhxeSAa
Option2:
Else, you can request, auth_time as a essential claim in the request.
you have to pass claims as a request parameter and send the auth_time as an essential claims.
{"id_token":{"auth_time":{"essential":true}}}
You have to do url encode and pass this as a value to the claims request parameter to the authorize endpoint. A sample request is given below.
https://localhost:9443/oauth2/authorize?response_type=code&scope=openid&&claims=%7B%22id_token%22%3A%7B%22auth_time%22%3A%7B%22essential%22%3Atrue%7&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2Fplayground2%2Foauth2client&client_id=KmerETRbZx2ErGhCqRfv4xhxeSAa
2. acr:
acr: OPTIONAL. Authentication Context Class Reference.
To get acr value in the id_token, first you need to pass acr_values as a request parameter with the all the acr values.
You can easily use ACR and AMR with WSO2 Identity Server by using adaptive authentication scripts. Through this the identity provider can enforce additional assurance in the user authentication flow. You can select the acr from the authentication scripts. Then Identity server will send the selected acr in the id_token response. You can follow this document to work with ACR in identity server and how to configure to get acr value in the id_token.

You may wanted to add those claims as Requested Claims in the Service provider.
https://docs.wso2.com/display/IS580/Configuring+Claims+for+a+Service+Provider

Related

How to use JWT with Ballerina

I read about JWT and i think i understand how it works, but when things come to ballerina examples i don't understand anything:
How do i set the algorithm which i want to use along with JWT and the expiration time?
How do i use a custom private key?
How can i get the token from this example for instance "https://ballerina.io/learn/by-example/secured-service-with-jwt-auth"?
May be how can i get the token using CURL (for testing purposes)?
Also i'm wondering how to use the JWT without the need of having a database with users and passwords..
I'm absolutely new to security and ballerina also. Can anybody help please?
Ballerina JWT module [1] provides following functionalities.
Issue a JWT
You can issue/generate a JWT by providing jwt:JwtIssuerConfig. You can configure username, issuer, audience, expiration time, signing algorithm, custom claims and configuration for signature (key-store config). Please refer to API docs of jwt:JwtIssuerConfig [2]. Example code can be found at [3].
Validate a JWT
You can validate a JWT by providing jwt:JwtValidatorConfig. You can configure expected issuer, expected audience, clock skew, cache configuratons and configurations for validating signature (trust-store config). Please refer to API docs of jwt: JwtValidatorConfig [4]. Example code can be found at [3].
Secure a service with JWT
You can use JWT to secure and HTTP service. The Authorization header of the inbound HTTP request will get validated and authenticated according to the provided configurations. Please refer to API docs of jwt:InboundJwtAuthProvider [5]. Example code can be found at [6].
Calling to a service with JWT
You can use JWT to call to an external server which is authenticated with JWT. The outbound HTTP request is prepared with the Authorization header according the provided configurations. Please refer to API docs of jwt:OutboundJwtAuthProvider [7]. Example code can be found at [8].
Answers for the questions:
How do i set the algorithm which i want to use along with JWT and the expiration time?
You can configure jwt:JwtIssuerConfig [2] as described above.
How do i use a custom private key?
You can configure the jwt:JwtKeyStoreConfig field of jwt:JwtIssuerConfig [2], with your custom private key.
How can i get the token from this example for instance "https://ballerina.io/learn/by-example/secured-service-with-jwt-auth"?
May be how can i get the token using CURL (for testing purposes)?
This is a sample service which is secured with JWT. The token used to invoke this service is provided at the bottom of the sample. How to invoke this service with CURL is also provided.
Also i'm wondering how to use the JWT without the need of having a database with users and passwords..
All of the above samples, does not need any database or file store. All the configurations are provided in the code itself. If there is any requirement to retrieve data from database, that is also possible.
References:
1 https://ballerina.io/learn/api-docs/ballerina/jwt/index.html
2 https://ballerina.io/learn/api-docs/ballerina/jwt/records/JwtIssuerConfig.html
3 https://ballerina.io/learn/by-example/jwt-issue-validate.html
4 https://ballerina.io/learn/api-docs/ballerina/jwt/records/JwtValidatorConfig.html
5 https://ballerina.io/learn/api-docs/ballerina/jwt/objects/InboundJwtAuthProvider.html
6 https://ballerina.io/learn/by-example/secured-service-with-jwt-auth.html
7 https://ballerina.io/learn/api-docs/ballerina/jwt/objects/OutboundJwtAuthProvider.html
8 https://ballerina.io/learn/by-example/secured-client-with-jwt-auth.html

GCP Pub/Sub authentication token not appearing in the request

I'm setting up cloud pub/sub service to receive push subscription messages on my backend by following the developer documentation.
For some reasons, the push subscription requests sent to my backend never have the "token" query parameter included, so my backend can't verify whether the push requests coming from my application or not. The following code from the developer doc is used to achieve the verification purpose:
// Verify that the request originates from the application.
if (req.getParameter("token").compareTo(pubsubVerificationToken) != 0)
{
resp.setStatus(HttpServletResponse.SC_BAD_REQUEST);
return;
}
According to the doc, I've verified that the "Service Account Token Creator" permission is granted to pub/sub's signing service, as well as enabled "push endpoint authentication" option and assigned an unique string to the "Audience(optional)" field in my push subscription in pub/sub.
I wonder if I'm still missing something here, or I've mistaken the way how the token audience works? Why does the "token" value not appearing in the requests my backend received? Any inputs would be appreciated!
As John Hanley said, the token is in the header. However, when I look your code, I don't know what do you want to "compare". The provided token change very often (because its life is very short) and you can't compare it to a reference token
But, you can extract claim information from token and then validate them. Here a snippet of Python code that I use for extracting email.
authorization = request.headers['Authorization'][7:]
b64_profile = authorization.split('.')[1]
profile = base64.b64decode(b64_profile + '=' * (-len(b64_profile) % 4))
print(json.loads(profile)['email'])
The code snippet quoted here is meant to verify the application token. This token is defined by the application developer as an environmental variable in appengine-web.xml (line 7).
The token that properly verifies the origin of the push request is a different one. It is generated by Cloud Pub/Sub and comes in the authorization header of the push request, in the form of a JWT. This bit of code shows how to verify the JWT (you can also check out the full sample):
// Verify and decode the JWT.
GoogleIdToken idToken = verifier.verify(authorization);
Hope this helps clear the confusion. :-)

How to authenticate to an API using an external identity provider?

I have the following setup on the same machine:
WSO2-AM
WSO2-IM-KM (Identity manager as key manager)
The identity manager federates authentication to an external OpenID identity provider.
What I've done so far:
Share the databases between the two components
Make WSO2-AM delegate the authentication to WSO2-IM-KM
Configure the external provider to the generated service provider (generated in WSO2-IM-KM when creating an application in WSO2-AM store)
The current behavior:
I can obtain an authorization code by calling the following URL : https://my.site:9444/oauth2/authorize?response_type=code&client_id=pkYcC4xFQ1jt6dQbdZAe6savv4oa&scope=phone+email+address+openid+profile&redirect_uri=https://my.site:9443/store/jagg/jaggery_oidc_acs.jag&nonce=3734e7d4c22f1&state=128d20e14c884, the authentication succeeds, then the jaggery_oidc_acs.jag endpoint fails
Since the jaggery_oidc_acs.jag endpoint fails, I manually retrieve the code then POST it to https://my.site:8243/token which returns me an access_token, a refresh_token, and an id_token
My problems :
How am I supposed to automate the manual step I described before? Am I in charge of creating a dedicated endpoint to do it, in order to keep the authorization_code obfuscated from the client, or is there a built-in endpoint in WSO2? If appropriate, what is this endpoint?
Is there an endpoint that generates the oauth2/authorize URL?
After further research:
I have found the following document https://docs.wso2.com/display/IS540/Authorization+Code+Grant that seems to indicate that I need a "client", but I don't have one, I just need my API to be authenticated with the external identity provider.
Answering to problem 01
If you want to use authorization code grant type to get access token definitely there should be a callback URL to get authorization code. If your callback URL is real no need to do any manual step, simply just retrieve authorization code from request query parameters sent to callback URL. You can check this behavior from playground2 sample application [1] where callback URL is http://localhost:8080/playground2/oauth2client.
Answering to problem 02
Please check OAuth2AuthzEPUrl tag in identity.xml
[1] https://docs.wso2.com/display/IS570/Setting+Up+the+Sample+Webapp

Can I use/trust an id_token to both validate a request and extract the user's information on the server?

I'm using node.js, lambda, cognito. An authenticated client sends tokens in the header to authenticate requests. The lambda function is verifying the JWT signature using the jsonwebtoken package.
I am trying to avoid making an external call on the server for each request to get the user's identity from their access_token, and I can see the id_token contains the information I require.
However, I read that using the id_token for request validation is not good.
If I call jwt.verify() on an id_token, am I right in thinking that:
1) It checks the id_token has not been tampered with by checking it against the signature?
2) The server can trust the id_token's payload once verified?
3) The id_token expires at the same time the access_token does?
If that's the case, then why not use the id_token in place of the access_token for requests with the server?
Or should I send both and check both?
In response to your questions:
Yes
Yes
Yes
You can use the id_token to validate requests. The Cognito docs say "The ID token can also be used to authenticate users against your resource servers or server applications"
See https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-with-identity-providers.html)
Technically the id_token is for verifying identity and the access_token is for verifying access, but you can use the id_token for both if you wanted.

Authenticate against WSO2 Identity Server with no browser and get SAML2 assertion message

I am trying to setup a service provider that uses WSO2 IS for authentication via SAML2. Now, wehave a use-case in which the user is a machine (i.e. an external program) that needs to access the service provider. Since the user is a machine, there is no browser and cannot use the WSO2 login form to complete the authentication steps, though it has been given a username and password since it is still a user.
My question is how can this non-GUI user participate in the SAML2 workflow (specifically pass credentials to WSO2 to obtain a SAMLV2 Assertion message) and access the service provider?
I tried to do the following as a simulation but I failed
1) curl -v -k http://localhost:8000/service_provider/login
2) Extracting the SAML message from the response:
curl --user username:password -v -k https://localhost:9443/samlsso?SAMLRequest=<ENCODED_REQUEST>
Basically, I was expecting to get a redirect response from WSO2 back to the service provider with SAML assertion message, but instead I got the following:
https://localhost:9443/authenticationendpoint/login.do;jsessionid=7QON18982323HWIH?commonAuthCallerPath=%2Fsamlsso&forceAuth=false&passiveAuth=false&tenantDomain=carbon.super&sessionDataKey=122JhQ-JQOJ-H8123&relyingParty=test-saml2&type=samlsso&sp=test&isSaaSApp=false&authenticators=BasicAuthenticator:LOCAL, which is the same url that is used when a human user authenticates using a browser.
I also tried using HTTP-POST Binding with "sectoken" form param as suggested in this article: http://xacmlinfo.org/2015/02/12/sso-without-identity-provider-login-page/ . But it didn't work either.
I also tried making SOAP requests to WSO2's AuthenticationAdminHttpsSoap12Endpoint service, specifically the "login" method. I used the JSESSIONID I got from the SOAP response to the above steps but the effect was the same. This is not a surprise to me since WSO2 does not use JSESSIONID to check if you are authenticated already (at least not for trying to grab SAML responses).
1.Get login form
Request
curl -v http://localhost:8000/service_provider/login
Response
Extract SAMLRequest and SSOAuthSessionID (if RelayState presents extract it too)
2.Send saml request to IDP using extracted valuses in step1(In browser this will happen through redirection)
Request
Endpoint : https://<is_host>:9443/samlsso
Verb :post
Content-Type:application/x-www-form-urlencoded
Parameters:[
SAMLRequest:<value from previous step>,
SSOAuthSessionID:<value from previous step>,
RelayState :<value from previous step>]
Response
This will give IS login page.Extract sessionDataKey from that.
3. Login by providing user name password
Reqeust
Endpoint:https://<is_host>:9443/commonauth
Content-Type:application/x-www-form-urlencoded
Verb :post
Parameters: [tocommonauth:true,username:xxxx,password:xxx,sessionDataKey:<extracted from previous step>]
Response
Extract SAML response
5.Post the saml resposne to ACS url of service provider