WSO2-IS how to retrieve tenant domain from JWT token? - wso2-identity-server

I need a way to put tenant domain info in JWT token (like a claim)?
I've to retrieve it in my java application

Believe you are talking about the ID Token of the OpenID connect spec.
Easier way to achieve this is to tick the Use tenant domain in local subject identifier option of your Service Provider application's Local and outbound configurations section. This will append the tenant domain at the end of the username in the sub field of the ID token as below. (Your Java application can process that extract the tenant domain)
"sub": "admin#carbon.super"
If you don't like that approach, you might want to write a custom ID token builder extending the default. Defined in the identity.xml file as <IDTokenBuilder>org.wso2.carbon.identity.openidconnect.DefaultIDTokenBuilder</IDTokenBuilder>

Related

How to create OAuth2 Opaque(Reference) Access Tokens

How to create OAuth2 Opaque(Reference) Access Tokens in apimanager 410? I followed enter link description here, but cannot find OAUTH token type when we create applications.
I want to create this application because of the issue enter link description here. if same token is sent every time we call the token api, this will work for us. Our tests need to get the token first and use it from there. there can be different apis calling in different times and this will expire the first token.
There is a lengthy manual method that lets you to create opaque tokens in APIM 4.1.0, but our recommendation is to proceed with the JWT token-based applications. This will reduce the load at the gateway with token validation which is a huge performance gain. Even if you used the same clientID, or secret Pair, you can change the scopes set with a device scope and I believe this should give you the ability to create multiple tokens at the same time.
Having said that, you can create opaque token in the below approach, but this will remove the user experience provided in the devportal and you have to use carbon console(https://localhost:9443/carbon) if you need to change your application.
log in to admin portal (https://localhost:9443/admin)
Open Key managers --> resident key manager (or whatever the key manager you have) --> and select Out Of Band Provisioning and save.
Log in to carbon console (https://localhost:9443/carabon)
Register a service provider.
Under Inbound authentication config, select OAuth/OpenID connect configurations and configure an OAuth Applicaiton
Add you application details from here as you prefer with the listed grant types and create an application.
Make sure to select the token issuer and default. This is where you select whether the token type is JWT or Opaque.
Once you save it, you can find the client ID secret pair in here.
Log in to devportal (https://localhost:9443/devportal)
Create an application.
Under the production Keys section, now you can see a new option enabled as provide existing OAuth keys.
Add the consumer key secret pair you created in the step 8.
Now you have created an application that generates opaque tokens.
In the latest API Manager versions do not allow generating opaque access tokens. You can use the following configuration to the deployment.toml of API Manager and disable token revocation on token renewal.
[oauth.access_token]
invoke_token_revocation_event_on_renewal = false

How to implement OAuth when the resource and auth servers are same

I have a Django Rest API with JWT authentication which is the backend for a Angular frontend. There are many clients who use the service with our frontend. Now some enterprise clients wanted to integrate the APIs from their system's backend. I don't want to remove JWT from current APIs. I am planning to create new APIs in the same backend with OAuth token for those users.
I wonder what is the best way to implement OAuth for this scenario.
I am thinking Client Credentials grant type is the best way.
Question1: Am I right that client credentials is the right approach ?
For those enterprise users, it is sufficient they get just access token through the UI interface so that they can access all our APIs.
But here the problem is one additional step of getting the Client ID and Client Secret first and using that to get Access Token.
Question 2: What is the use of client ID and client secret ?
Question3: Should my backend hide the process of generating Client ID and Client secret and just give Access token (or) give them Client ID and Client Secret and ask then to generate access token ?
Question 4: If I am giving them Access Token without client id and secret, is that fine to have infinite expiry time? and
TLDR; How to implement OAuth when the resource server and auth servers are same ?
There are 4 grant types in oAuth2 which is meant for different scenarios.
client credential : the consumer (app) make calls to back-end using the bearer token created using apikey(or clientId) and secret only. Mostly used for anonymous calls where generic information is retrieved.
Resource owner password credential (ROPC) : the consumer (app) make calls using the bearer token created using apikey, secret, username and password. Mostly used when you(your authorization server) already know the users(user database is handled in your own system).
Authorization code : the consumer (app) make calls using the bearer token created using an authorization code. The authorization code is provided by a 3rd party (which actually has/manages the logged in user data) and the created authorization code linked to the logged in user. Google and Facebook log in for various sites is a typical example. Facebook/Google gives an authorization code for those websites and they exchange that code for a token.
Implicit grant : Mix of password credential and authorization code. Instead of authorization code, you get a bearer token from the 3rd party authorization server.
Question1: Am I right that client credentials is the right approach ?
I think you can use CC if there is no user level logics in your backend. If userlevel involved, may be ROPC is a better choice
Question 2: What is the use of client ID and client secret ?
Client ID and Client Secret is very similar to username and password in an application level, which is used to obtain bearer token.
Question3: Should my backend hide the process of generating Client ID and Client secret and just give Access token (or) give them Client ID and Client Secret and ask then to generate access token ?
If you are implementing oAuth2, your consumer should create the access token. But looking at your use case, may be even a simple hash of userId+timestamp is sufficient. ;)
Question1: Am I right that client credentials is the right approach ?
Yes. Providing the new APIs do not need to be called in the context of an end user.
Question 2: What is the use of client ID and client secret ?
The client ID allows the auth server to identify the application
requesting the token (it's often carried through to the access token
too, allowing the API to identify the calling application).
The client Secret means the auth server can trust that the client is
genuinely who he says he is as only he should have the private client
secret for his public client ID.
It's effectively a username and password in this scenario.
Question3: Should my backend hide the process of generating Client ID
and Client secret and just give Access token (or) give them Client ID
and Client Secret and ask then to generate access token ?
Your Auth server should issue the client credentials to the application once and the application should provide those credentials every time they wish to obtain a token via the client credentials grant type.
authorization code grant, or implicit grant might be more suitable for this scenario. The first one allows you to add an authentication step before the tokens are returned to the users (might be useful if you want to integrate your JWT authentication to this as well) and the second one is mainly used for single-page applications, and does not include an intermediate authentication step. This one would be useful if you want to improve efficiency.
client_id and client_secret are given to you when you register a client application in your identity provider(authorization server). This client application does not mean an application or an API belonging to your clients, but your own application to which you plan to incorporate OAuth(and OIDC). These two parameters are useful when making the requests to authorization in order to obtain tokens. The server uses those values to determine whether the request is made by a valid application. Only you have access to those values as you will be the one who's registering the application with the server.
I think this question is answered in the previous section.
I think it would be better if you go through this before doing any implementation. It provides most of the basic knowledge you should have before implementing an OAuth system. I hope this answer was useful to you.

How do I integrate amazon cognito login in postman?

I was using Amazon Cognito user pool for login. When I access my web application, I get a redirect to
https://<domain>.auth.<region>.amazoncognito.com/login?response_type=code&client_id=<client id>&redirect_uri=<callback> .
Once logged in with the username/password of a user from the pool, I will be redirected to the callback URL with the code as a query parameter. I can use this to get tokens. How do I integrate this in postman so that I can use the token for my upcoming request?
I have an example of doing this...
The callback URL as defined in the Cognito User Pool console under App Integration / App client settings.
The URL for the login endpoint of your domain. This will be under Cognito User Pool / App Integration / Domain Name
Client ID is found under Cognito User Pool / General Settings / App clients
List the scopes you want to include in the Access Token. These must be enabled under Cognito User Pool / App Integration / App client settings. These can be either standard or custom scopes. Custom scopes are defined under App Integration / Resource servers and must include the resource server ID (e.g. https://myresource.com/myscope)
Click Request Token
You may now log in to your Cognito User Pool and receive an Access Token!
The problem is that once you have the Access Token it isn't usable within Postman because Cognito expects it to be bare and Postman automatically prepends 'Bearer' to the token:
The token can be used in cURL though:
curl -i -H "Authorization: dyJraWQiOiI1YVcwTUlqN1hBaHg4Yzh4Q3JNT2RsQjhZWjlCR3NQOE9BbkFlVFJtUklRPSIsImFsZyI6IlJTMjU2In0.eyJzdWIiOiI3YmEwZmMzOC01ZDcwkYS05MTI5ZTBmYTUzNTEiLCJ0b2tlbl91c2UiOiJhY2Nlc3MiLCJzY29wZSI6Imh0dHBzOlwvXC9hcGkubXk5MC5jb21cL3BvbGljZURlcGFydG1lbnRzLnJlYWQiLCJhdXRoX3RpbWUiOjE1NDA1OTIzMTYsImlzcyI6Imh0dHBzOlwvXC9jb2duaXRvLWlkcC51cy1lYXN0LTEuYW1hem9uYXdzLmNvbVwvdXMtZWFzdC0xX2xIbGo4NXpRYSIsImV4cCI6MTU0MDU5NTkxNiwiaWF0IjoxNTQwNTkyMzE2LCJ2ZXJzaW9uIjoyLCJqdGkiOiJhN2JiOWU2MC1kNmY1LTQ3ODYtODMwYi0xODdkZDZmYTZlODAiLCJjbGllbnRfaWQiOiI2MzhlYmZ1dTdiZDRkMXVkYnRzY2pxcnJncyIsInVzZXJuYW1lIjoicm9qbyJ9.O_GAxfFX3IQfLUu5Hxr05Wrk_2QDwNSL8tvDdEU0Dzs9d1XhQPafT6ney6yiGnKPOwsO8HhWdbT1QdDmByjuwQAURf1Da4Au7c-yhfgJcqWuHWZ4mledTSP8ukXqihMb4PoaDdU4JXyOdMLa50dBXVMgJNyXTpIulWOxFhiTW6DeQbnxNDk94cGNz_CTKCEqKStiloFZfLR7ndSrWqdOQ_SU__YV0RyKXZyK5yguv3nkUcI6cuKpbPVIZ5DNdpufbrtOLuZcC6HePBKrbTKjSZCt5-swy3YrwnY4ApTX7QUFzof6FylWaLA_KVP3Zv6ksSJ_IjBMFH1NRVHh4lbsOA" \
https://xxxxx.execute-api.us-east-1.amazonaws.com/v1/myresource/1234
by yl.
Thanks to Robert Jordan for his above postman OAuth2.0 configuration post.
I'll try to cover here the entire Cognito user pool definition part to make it easier.
Ok,
Open the Cognito console and follow the bellow stages:
1) create new user pool
name: Test1
left panel menu->Attributes
Select the following radio buttons:
o Email address or phone number - Users can use an email address or phone number as
their "username" to sign up and sign in.
o Allow email addresses
And checkboxes:
[v] email
[v] name
Screenshot:
Press the [Create Pool] button.
(if not available yet to the wizard - press [Review Details] option on the left panel menu)
2) left panel menu->App Clients
press: [add app client]
App client name: me1
clear all checkboxes but the:
[v] Enable username password based authentication (ALLOW_USER_PASSWORD_AUTH)
Leave Radio buttons as is:
o Enabled (Recommended)
Screenshot:
press [create app client]
3) copy and keep the 'App client id'
this is a string format similar to 5psjts111111117jclis0mu28q
Screenshot:
4) left panel menu->App Client settings
Enabled Identity Providers: [v]Select all
[v] Cognito User Pool
Callback URL(s): put the api gw url or https://www.google.com/
OAuth 2.0
Allowed OAuth Flows
[v] Implicit grant
Allowed OAuth Scopes
[v] openid
Screenshot:
5) left panel menu->Domain name
put a string in the prefix field, for instance: music123456789
check if available using the 'check' button.
your domain now is: https://music123456789.auth.us-east-1.amazoncognito.com
Screenshot:
6) left panel menu->Users and Groups
press [Create user]
Username (Required): Your.Mail#company.com
clear all [v] check boxes
Temporary password: Xx123456!
eMail: Your.Mail#company.com
7) in POSTMAN
Press new Request
enter the 'Authorization' tab
Select TYPE: OAuth 2.0
press the [Get new Access Token] button and fill in:
Token Name: myToken123
Grant Type: select 'implicit' from the listbox
callback URL: https://www.google.com/
(as in clause 4 or in cognito console->App Integration->App client settings)
Auth URL: https://music123456789.auth.us-east-1.amazoncognito.com/login
(as in clause 5 + '/login' suffix, what you have defined in cognito
console->App Integration->Domain Name)
Client ID: 5psjts343gm7gm7jclis0mu28q (the app client id - as in 3,
what you have defined in cognito console->General Settings->App clients)
Scope: openid (as in 4, what you have defined in cognito console->App
client settings->Allowed OAuth Scopes)
COGNITO to OKTA idp configuration
When connecting Cognito to Okta IDP, Configuration should be as follows:
Okta Setup
Cognito Setup
Postman setup
As an addition to very through explanations of Robert Jordan and ylev, I made it work by using the id_token instead of the Access Token.
In the token details page, copy the id_token and add it to the header manually without Bearer prefix:
Source: https://github.com/postmanlabs/postman-app-support/issues/6987
For those wanting to move away from the deprecated "implicit" grant to the recommended "authorization" aka "authorization code" grant, you'll want to have the following in Postman:
Grant Type: Authorization Code (Authorization Code with PKCE would prevent the code from being used by anyone else if it were intercepted in transit but either or... you probably want to start with getting "Authorization Code" working.)
Callback URL: https://oauth.pstmn.io/v1/callback (or whatever Postman sets it to when you check "Authorize using browser"
Auth URL: https://{app name you chose when creating the custom auth domain}.auth.{aws region}.amazoncognito.com/login e.g. https://myapp.auth.us-east-1.amazoncognito.com/login. You can find this in AWS Console -> Cognito -> the user pool -> App Integration tab -> Domain section -> Cognito domain (use the Actions dropdown to create a custom domain if you don't already have one).
Access Token URL: https://{app name}.auth.{aws region}.amazoncognito.com/oauth2/token e.g. https://myapp.auth.us-east-1.amazoncognito.com/oauth2/token.
Client ID: The Client ID corresponding to the "App Client" (e.g. the web app users will be authenticating through Cognito to use), found in AWS Console -> Cognito -> the user pool -> App Integration tab -> App Client List section -> the App Client.
Client Secret: An optional added security measure. This should never be sent to the web app as the client secret could then be extracted by a nefarious user via Chrome Dev Tools or the like. You can (and should) however use Client Secret with backend applications e.g. the API service backing your frontend web app. This is a decision that has to be made in AWS when the App Client is created within the Cognito User Pool, but don't fret- App Clients are easy to create/delete/recreate if you change your mind or pick the wrong setting.
Scope: OAuth uses "scopes" as a means of defining what the application which holds and uses the access token (e.g. some web app) can do/access on behalf of the user whose account it's using. It's similar to authorization in a web app (e.g. only users in the "admin" group can access the settings page) but it's meant to be authorization with respect to a user's metadata, so typically that manifests as user metadata the app has access to, for example the user's calendar or contacts or phone number. OAuth scope is not meant to replace an app's authorization system (e.g. RBAC) so if you're just making some web app and just need Cognito to handle user signup, storing and resetting passwords for users, etc. you can more or less ignore OAuth "scope", though you should probably be setting the "Scope" value in Postman to something like "openid email" (Scopes are separated by a single space and you can't request and obtain the "email" scope without also requesting "openid") so you at least get the user's email address in the access token to compare with your "Users" table in your app's database. Scope makes more sense and becomes more relevant in a scenario where your web app is authenticating with an actual third-party (not your own Cognito user pool), like Facebook or Google. Maybe you're making an app that syncs users' friends' contact data from Facebook to.. I don't know, a CSV file downloaded to your computer for backup purposes. In this case you want to request from Facebook's OAuth server the "friends-list" scope or whatever Facebook decided to call that scope. On the other hand, if you just need Facebook as a means for allowing your users to easily sign in to your app without having to create an account, you don't need the "friends-list" or any other scope from Facbeook (maybe just the scope that gives you the user's email address?).
Other fields:
Client Authentication: Send client credentials in body
Type: OAuth 2.0
Add authorization data to: Request Headers
Sources:
https://www.czetsuyatech.com/2021/01/aws-generate-cognito-access-token.html
https://aws.amazon.com/blogs/mobile/understanding-amazon-cognito-user-pool-oauth-2-0-grants/
https://api.slack.com/legacy/oauth-scopes
If your client supports USER_PASSWORD_AUTH you can request valid bearer tokens using the aws client.
read -s -p "Password: " && \
aws cognito-idp initiate-auth \
--client-id <client id> \
--auth-flow USER_PASSWORD_AUTH \
--auth-parameters "USERNAME=<username>,PASSWORD=$REPLY"
This can be added to Postman under Authorization / Type: Bearer Token.
For Postman 8.5.1 and AWS Chalice + Cognito user pool on the backend I have working example:
Cognito > User pools > > App integration > App client settings
About vars:
{{cognito_callback_url}} - Your Callback URL(s) from App client
settings
{{cognito_auth_url}} - Cognito > User pools >
> App integration > Domain name + /login
(https://.....auth.ap-south-1.amazoncognito.com/login)
{{cognito_client_id}} - Your App client web id from App client
settings
{{cognito_scope}} - Use 'openid'
Now click the Get the new access token in the bottom and authorize yourself using existing user data from pool
I thought i would post some more information about using cognito with an elastic load balancer. AWS load balancers do not current support auth via headers :( you can get it working on postman by copying cookies from a successfull web request into the postman request
The use-case you want to implement can be achieved by using the OAuth 2.0 authorization. If you can get the Auth URL/ Access Token URL, Client ID, and the Client Secret- you should be able to do it.
Here's a link to the documentation of the various authorization types we support including the above mentioned one- https://www.getpostman.com/docs/v6/postman/sending_api_requests/authorization.
Cheers.

Office365 resource end points for O365-D-vnext (dedicated, not multi-tenants) deployment

We are having issues with obtaining access tokens for Sharepoint/Exchange resources for a non-multi-tenan Office365 deployment.
This tenant has an O365-D-vnext (dedicated, not multi-tenants) environment which seems to use a different resource end points for sharepoint and exchange, and possibly the management APIs as well.
We use the 'client credential flow' (app-only) to authenticate the global admin for this tenant. The authentication went through, and we got back an auth token (which we discard as it’s not applicable in app-only authentication flow) and tenant-id (we verified the tenant id with the customer). We then tried to get tokens for 3 different APIs using
login.microsoftonline.com//oauth2/token
Here is where we are at with this:
1) We were able to get token for
https://graph.windows.net
and access the active directory groups (we should be able to fetch the users as well)
2) We were able to obtain an access token for exchange resource endpoint
https://outlook.office365.com/
but when we tried to use it, we got 404 for users that we know have mailboxes. We are not sure if outlook.office365.com works for O365-D-vnext (dedicated, not multi-tenants) environment.
3) We were able to get token for
https://{tenant}-my.sharepoint.com"
but when we tried to use the token to access user’s Onedrive, it returned this error: {“error":"invalid_client","error_description":"Invalid audience Uri 'https://{tenant}-my.sharepoint.com/'} . We were told by our customer that this endpoint would not work for their non-multi-tenants environment.
We subsequently tried a couple of other vanity URIs that the users of this customer use to access their sharepoint onedrive documents. But we were NOT able to get token for the URIs provided by our customers. We received the following error when using these URIs provided:
{"error":"invalid_resource","error_description":"AADSTS50001: The application named https://<tenant-my-site>.com was not found in the tenant named https://<tenant>-my.sharepoint.com/. This can happen if the application has not been installed by the administrator of the tenant or consented to by any user in the tenant.  You might have sent your authentication request to the wrong tenant.\r\nTrace ID: … ”error_codes":[50001] …}
Any ideas on how to get access tokens for this type of deployments?

WSO2 Sharing super tenant web service to other tenants

I would like to share web service which is deployed in super tenant to other tenants. As far as I know everyone can access the super admin services if they are using http:// localhost :8280/services/echo?wsdl url. But I do not want just to access super tenant application, I would also like to see request count on correct tenant. Should I have to deploy the same application to every tenant and call service with proper url (http:// localhost .com:8280/services/t/tenantname/echo?wsdl) to collect the request counts?
Is there any other way to do this? For example maybe I could put header variable to my request which is showing, which tenant is calling the application etc., and with this kind of approach, I do not have to deploy my service to other tenants.
You can use a code something like,
int tenantId = MultitenantUtils.getTenantId(this.getConfigContext());
to get the tenant ID of the current tenant and send it either in the message itself or in the header. Then you can record the tenants accessed in the server side, by counting the tenant IDs.
This will help you to get the tenant ID.
One possibility is to deploy the application at each tenant. Then you get a separate URL for each.
Or else you can make your service multi tenant aware. For this you need to make the service secured. When log into the service, we can determine the tenant using the user name. For an example foo user should be a super tenant user while foo#bar.com should belongs to bar.com tenant. In this case carbon framework, does this authentication and set the tenant details to carbon context. You can access that at the service level. eg. CarbonContext.getCurrentContext().getTenantID() or with the method Maninda has mentioned.
org.wso2.carbon.tomcat.ext.internal.Utils class has a function which name is getTenantDomain.
I have changed this methods to find tenant domain from headers, so it is working like a charm :)
I think WSO2 also thinks to customize this method.