How do I implement #POST in Retrofit and save oAuth2 token? - rest

I'm using Kotlin and Retrofit2
What I would want to do:
I would want to get an access token and save it somewhere so I could use it later. How implementation should look like using Retrofit2? Especially "#POST" operation? I have to provide login, password, client secret and client id in order do get oAuth2 token. And what should I do after declaring #POST operation, where should I initialize this and where to save this token.

Related

Why is it needed to save the refresh token in the database?

I am trying to understand this access_token, refresh_token feature. And this is what I understood:
-- LOGIN:
CREATES access_token;
CREATES refresh_token, sends to DB;
SENDS refresh_token + access_token to client;
access_token expired:
API automatically CREATES a new access_token, using refresh_token;
refresh_token expired: API DENIES all requests, forcing the client to login again.
And i heard that you need to save the refresh_token on a 'sessions' table of database, or smth like it. But i can't understant why, since the client will/may send the refresh_token on all requests. Making it useless to save to DB.
I don't know if i got anything wrong, i hope you can help me out!
What is a little bit awkward (or unclear) in your example - which system creates access and refresh tokens, and sends them to the customers?
Based on the description, I would conclude that this is the identity provider - the client authenticated themselves and got those tokens as a result.
Now when the client calls an API (on a resource provider), they have to include the access token with each request. The resource provider would take the access token and validate it. If the access token is not valid, the API just have to return "access denied".
The client has to use the refresh token to get the new access token from the identity provider and repeat the call to the API on the resource provider.
This would be the typical usage of the flow.
The other common use case is to allow a backend system to do api calls on behalf of the client - in those cases, the backend system has both access token and refresh token; so it can maintain the logged in state even if the client is not around.
It might be that your example is some kind of hybrid solution - both customer and the backend do some calls to IDP.

User ID attribute in JWT token to the backend WSO2 APIM

I'm having trouble implementing the following use case. I need to pass the User ID claim to the backend. I've enabled enable_outbound_auth_header so that the token I get from the application arrives to the backend. I've managed to add the User ID to this token. I want to use JWT grant, Code grant, client credentials grant and APIKey. However, User ID is only added to the token on code and JWT grants. The way I did it was using OIDC scopes.I've seen in docs that I can use apim.jwt to pass enduser attributes, however I haven't managed to pass User ID. Is there any way to achieve this? (without custom generators)
In the case I have to implement a custom token generation I'm wondering which one to
implement. I've seen that there are many possibilities. Should I implement a token generator? Will this one work for apiKey token? I think there are at least four possible toke generators (gateway token generator, jwt token generator, oauth token generator and oidc token generator. Which one or how many should I implement?
I ended up implementing two custom token generators. I just inherited from the default class implementation for each generator and added the userId claim. Then I added them in the deployment.toml
For the apikey generator (extended DefaultApiKeyGenerator) simply added
[apim.devportal]
url = "https://localhost:9443/devportal"
api_key_generator_impl = "com.apikeygenerator.CustomAPIKeyGenerator"
The other one I implemented was the oauth token generator (extended JWTTokenIssuer). Adding this one to the configuration using
[[oauth.extensions.token_types]]
name = "JWT"
issuer = "com.oauthjwtgenerator.CustomOauthJWTGenerator"

Decoding Keycloak JWT Token

I'm trying to validate (and read roles from) a JWT Token. Sadly I can't use any adapter or auto configuration due to my overall application architecture.
It's no problem to decode the token like any other JWT Token, but I wonder if there is a library from Keycloak to archive this goal. (For example Just Parse the token to something like a KeycloakJWTToken and verify it by grabbing the secret from Keycloak Server or so)
Any easy-to-use client or so?
I'm using the Jose4J library:
https://bitbucket.org/b_c/jose4j/wiki/Home
Reading the claims inside a JWT token is straightforward:
import org.jose4j.jwt.JwtClaims;
import org.jose4j.jwt.consumer.JwtConsumer;
import org.jose4j.jwt.consumer.JwtConsumerBuilder;
public void parseJWT(String token) throws Exception {
JwtConsumer consumer = new JwtConsumerBuilder()
.setSkipAllValidators()
.setDisableRequireSignature()
.setSkipSignatureVerification()
.build();
JwtClaims claims = consumer.processToClaims(token);
System.out.println("* Parsed token: "+ claims.getRawJson() );
System.out.println("* Expiration date: " + new Date(claims.getExpirationTime().getValueInMillis()) );
}
More examples are available on GitHub:
https://github.com/pvliesdonk/jose4j/blob/master/src/test/java/org/jose4j/examples/ExamplesTest.java
Last remark: you do not need a key nor a secret to parse the JWT, but if needed, you can use the server (public) key to verify the token was signed by the keycloak server you are trusting.
The JWT website is listing all libraries for Token Signing/Verification:
https://jwt.io/#libraries-io
Keycloak access tokens are indeed JWT tokens. So, you can make full use of existing JWT libraries, including for validation as stated in the Keycloak official documentation:
If you need to manually validate access tokens issued by Keycloak you can invoke the Introspection Endpoint. The downside to this approach is that you have to make a network invocation to the Keycloak server. This can be slow and possibily overload the server if you have too many validation requests going on at the same time. Keycloak issued access tokens are JSON Web Tokens (JWT) digitally signed and encoded using JSON Web Signature (JWS). Because they are encoded in this way, this allows you to locally validate access tokens using the public key of the issuing realm. You can either hard code the realm’s public key in your validation code, or lookup and cache the public key using the certificate endpoint with the Key ID (KID) embedded within the JWS. Depending what language you code in, there are a multitude of third party libraries out there that can help you with JWS validation.
Besides, in Java EE, using the Keycloak Java adapter, the roles are typically mapped on the user Principal and i.e. allows isUserInRole(). That's one of the goals.
Also it is possible to cast the Principal from the SecurityContext as a KeycloakPrincipal, then obtain in turn a KeycloakSecurityContext from it. Using the KeycloakSecurityContext you have access to both ID and Access tokens (when applicable) and can read their properties, attributes and claims.
Note that it is also good practice, and simply useful, to use the Keycloak UI to "evaluate" your tokens. For instance, you can see the generated token in the Client Scopes tab (under Evaluate), as well as evaluate your policies and permissions in the Authorization tab of your Client(s) (under Evaluate).
Cf. https://www.keycloak.org/docs/latest/server_admin/#_client_scopes_evaluate
That's probably the best way to debug and test, while setting up your Client(s).
If you select a user in the Evaluate screen, the following example data is generated:
Generated Access Token (...)
Generated ID Token (...)
Generated User Info (...)
All examples are generated for the particular user and issued for the particular client, with the specified value of scope parameter. The examples include all of the claims and role mappings used.
Source: https://www.keycloak.org/docs/latest/server_admin/#generating-example-tokens-and-user-info

How to download a file secured with IdentityServer

I want to be able to download a file from an API call. For argument's sake, let's say it's an automagically generated PDF file.
I have two problems:
Anchor tags can't add Authorization headers to the request, only XHR can.
XHR requests cannot download files.
My solution is to write my API with an [AllowAnonymous] end point in it, which takes the access_token as a parameter. I then validate the access token by hand and return a 401 or stream the PDF.
Is there a better solution than this or, if this is the best solution, how do I validate the access_token within the API?
This approach is totally fine.
If you want to use middleware to validate the token - it depends which middleware you are using. The plain Microsoft JWT bearer middleware has some events you can implement to retrieve the token from a query string alternatively.
The identity server token validation middleware has a TokenRetriever property which also allows you to retrieve the tokens from multiple/alternative locations.

Is there a standard way to generate a RESTful access token?

I just touch with RESTful API. Basically, no matter what the rest api is, the first step is to get access token. However, I have been in two different situations:
Have client_ID, Client_secret, and username, password.
POST: api.XX.com/1/authorize?
Authorization:Basic [client_id:client_secret] must be base 64 encoded
Content-Type: application/json
Then, I get access token without timeout.
Have app_key
GET https://api.XX.com/authorize?
response_type=Pin&
client_id=APP_KEY&
scope=SCOPE
After get Pin, register in web application. Then use code to request access token.
POST https://api.XX.com/token?
grant_type=Pin&
code=AUTHORIZATION_TOKEN&
client_id=APP_KEY
Finally, I have access token and reflesh token. access token will be timeout after 1hr.
So I need to use refresh token application access again.
I just want to say, Even the RESTful doesn't have Standard, access token application methods are big different. I think the first one is better. The first one makes things simple.
Because I just start to call RESTful Web Services, I would ask:
Are these two authorization methods common way? Is there a third method to get access token? Any comments please. Thanks.