Keycloak id_token is null with REST authentication - java

While using REST authentication with Keycloak, my id_token is null (server side). To connect to the application, I am using the following URI:http://localhost:port/auth/realms/{name}/protocol/openid-connect/token provided in the documentation (with the appropriate form params grant_type, username, password,... see here). In response (client side) I can retrieve the access_token and id_token. Then, I am using the "Bearer" authorization in the HTTP header to discuss with the server. While using my custom client, the id_token is null in the server side. Can someone explain me why?
(Just to be clear, all is working well by using the keycloak authentication page)

It seems that the id_token is only used while using the GUI authentication interface. To bypass my problem, I added my custom metadata to the access_token, then replaced all the reference to the id_token (on server side) to the access_token. By doing this, the application is fully compatible with the OAuth2 protocol.

Related

Using Keycloak as Authorization Server with Zuul as API Gateway

I'm currently building a microservice backend with Spring Boot, Zuul as API Gateway and Keycloak as Authentication and Identity Provider.
For my frontend I'm currently using Angular as an SPA with the Authorization Code Grant.
The API Gateway should validate each request (if the user is authorized) via Keycloak before sending it to the microservice.
Each microservice ( ResourceServer) should be able to get the user information for the current request by using the introspection endpoint.
What would be the correct way to implement this, or is this even a bad design and I'm on the wrong way?
Typically, you have two options:
JWT given to client: The client (Angular SPA in your case) authenticates and receives the JWT. The JWT token can be verified by an party using the Keycloak public key. It also contains a lot of user information.
JWT given to back-end: The client is given the temporary authorization code grant. It is forwarded to a backend system, which exchange it for the JWT. The backend system will need to create a user session, store the JWT in the user session and use a session ID cookie (or a similar mechanism) to match the client to the session.
The proposed architecture is a mix of both worlds. Option 1 would be more natural.
Option 1: The client authenticates with Keycloak and gets the JWT. It then attaches the JWT to each request. Zuul can check that the JWT is signed by the trusted Keycloak instance and that it has not yet expired (without contacting Keycloak). The microservice can do the same. If more than the basic user information is needed, the microservice can contact Keycloak.
Option 2: I can't tell you if option 2 is possible with Zuul. Let's assume that it is. If so, the gateway would redirect unauthenticated requests to Keycloak. Once the client has received the authorization code grant, it is redirected to the API gateway. The API gateway then contacts Keycloak to exchange the code for the JWT and saves it in a session. The client is given a session ID. When a request is forwarded to the micro service, the JWT is added to the request. The client never sees the JWT.
These descriptions assume that you are using Open ID Connect, which is supported by Keycloak. If you use an OAuth 2 setup, most things still apply but a few details are more complicated, e.g. instead of the JWT containing all the information you get an opaque token that can only be validated against an introspection endpoint.

Is it possible to get authorization_code in OAuth 2.0 without web browser in Java?

As I understand, in authorization code flow we need to get authorization code and use it to get token after. We can get this code only when user confirms specified access. After that browser redirects us to redirect_uri and response will contain authorization code as parameter. So, the question: is it possible to get this authorization code without browser or any self made UI? Can we get it in application after correct request to, for example https://mysite.tuz/authorize ?
As you are using authorization code flow, the client requires a user agent (i.e browser or mobile app) to get the authorization code from the authorization server.
The whole purpose of using authorization code is that it can be passed via the user's web browser (user agent) instead of passing the access tokens directly via the web browser (user agent) which is not desired. Using authorization code,the Client then can directly retrieve an Access Token from the authorization server.
So the user agent is required to get the authorization code and act as an intermediary between client and authorization server.
If you do not require a browser then authorization code flow may not the correct choice. OAuth 2.0 supports several different grants i.e ways of retrieving an Access Token. Deciding which one is suited for your case depends mostly on your Client's type.
This might help you in deciding which flow to use
https://auth0.com/docs/api-auth/which-oauth-flow-to-use
You should use client credentials to obtain token without browser or any client. But if you need to use user credentials to get access token and id token of the user without browser or mobile app you need to implement you own client which will do the necessary logic for you and fetch the token for you. I already did it in java for the testing purpose. I don't know why you need to do it but you can implement your own client in almost any programming language . But in case you will decide to go this way you have to handle lot of things.
I expect your authorization server requires Proof-Key for Code
Exchange (PKCE) - so first of all before you start to communication
with server you have to create code verifier and code challenge
(google can help you with that :) in java it is quite simple)
Then you should start communication with server sending get request to url which ends with 'auth' you should send query params as: response_type (which is 'authorization_code' in your case), redirect_uri, client_id, code_verifier, code_challenge, scope, code_challenge_method (probably 'S256')
Then you receive I think two redirects from server so it is better to have some client in java which will automatically call those redirects. I used apache http client for my implementation. It has lot of features.
After successful redirect server will return login page to your client. It depends on authorization server but in this page you should put the data as username and password and submit the page. I have simply parsed the returned page and get the url for user authentication from it and simply make post request to that url with user credentials data sent in encoded form entity. In apache http client you will have all cookies from previous communication set (until you close the client) since apache http client automatically set all cookies returned in previous communication from server.
After make authentication request server will send you two redirects and you can store those redirects int http client context which you will provide for http client when you call authentication url.
In the last redirect there will be query parameter sent be server named "CODE" this is really important for you since you will use it to get token from the server
And finally you have to make one last post request to authorization server with url ended as token. So make a post request with GRANT_TYPE, REDIRECT_URI, CODE (you received in previous redirect), CLIENT_ID, CODE_VERIFIER (you have generated at the beginning);
Then authorization server will send you token and that's all

How to achieve login in java consuming a web service?

I have a project in java which utilize j_security_check and ldap for authentication. Now my employer want to change it to an authentication using a webservice provided . What they gave me is actually a link as shown below
"http://11.111.111.111/ADManager/ADlogin.asmx"
I am a total newbie to java and webservice.All I know is if we provide some data to a webservice it will give a response. my doubts are
Is it possible to create a login consuming that link they provided?
Should I ask them for more info?
Is it posible to replace the j_security_check and ldap already configured in my java project?
P.S : The one who assigned me this task doesn't seems to have much knowledge either.
The short answer is you can.
You need to do the following:
Each web resource is protected by a (servlet) filter. This filter checks each incoming request and validates the token which needs to be on the http header. If the token is valid then the request is served. If the token is invalid the filter is going to send back http 401 unauthorized. Then redirect to the loin page.
Login with rest service:
1) Create a custom login page with username/password field.
2) Create a rest web service, receives username/password. It will check the credentials against an external access management infrastructure like OpenAM.
3) First, call auth(username, password) rest api to get the auth token. If the given credentials are okay then just send back the auth cookie to the client with HTTP 200 response code.
4) Then, you can call protected rest apis. You need to send auth cookie with your request each time.
5) Servlet filter (or something similar) checks each incoming request and validates the token. If the token is valid then the request goes forward to the rest method, if not you need to generate an http 401/403 response.
I suggest you not to write your own authentication layer, please use an existing one, for example OpenAM.
This forum topic explain everything you.

Securing Rest Web Service for Public Authentication - Server to Server

I've a have a public RESTful API that is used for user authentication for a web application that accepts the user id and password in clear text (see below). The username is passed in the url path as a path parameter and the password is a query string parameter. The HTTP GET comes from another web application on the server side (http client request), is this API secure? I was under the impression that the URL can not be seen if the request is going from server to server. My main fear is that someone could use something like firebug and see the traffic and get the userid and password.
REST end point:
HTTP GET https://host:80/user/joebob?password=pass123
Someone most definitely could see the username and password with a simple network sniffer. If you are POSTing the request, why are the parameters in the URL? They should be in the body like a normal POST, then at least the SSL protection kicks in and people can't sniff them. Another option would be for you to look at HTTP Basic Auth.

Kerberos authentication from my custom servlet?

I do the below steps to get the security token from browser for Single Sign on authentication.
I am able to find the Token from http header. My question is:
a) How do I verify this token with active directory?
b) How do I find username from this token?
While googling it seems Java API has Kerberos5 login module to do what I was expecting. But almost all pages lacks simple examples.
The Web client accesses a AS Java resource with a GET request.
The AS Java sends back a 401 response code (unauthorized) with a request to initiate SPNego authentication by setting the HTTP header “WWW-Authenticate” to “Negotiate”.
The Web client recognizes that the AS Java host is a member of the Kerberos Realm and procures a Kerberos Client/Server Session Ticket for the AS Java from the KDC.
The Web client then sends the Kerberos Client/Server Session Ticket to the AS Java wrapped as a SPNego token in the HTTP authorization header.
The SPNegoLoginModule reads the token from the HTTP request and feeds the Kerberos implementation of the JDK with it.
The result is either successful client authentication or failure when the client request is rejected or another roundtrip to the KDC is necessary. In the case of failure, the Kerberos JDK implementation of the AS Java generates and sends back to the Web client an output token. The output token is wrapped as a SPNego token and sent in the HTTP authorization header.
Any help would be appreciated.
There is no response for long time. Found answer myself from various site on the internet.
Documented my experience in below link:
http://webmoli.com/2009/08/29/single-sign-on-in-java-platform/
Here's an open source library, http://spnego.sourceforge.net, that has some examples of what you want to do.

Categories