Having Authentication Token and Login Credentials, How we can automatically login user or how to generate a login-actions/authenticate url

In the last step of our custom registration flow, users will gain an authentication token (access_token and refresh_token) after entering their new password.
Having that we can initialize a logged-in instance of Keycloak javascript class. However; this won’t set the sso cookies (KEYCLOAK_IDENTITY, …).

Is there a solution to set these cookies or can we generate a login-actions/authenticate URL and post the user’s credentials in a post request (custom login form)?

Did you have a look at this suggestion? Given an access token, it sets the SSO cookies.

1 Like

Thank you for the suggestion
After some changes to handle the CORS issue, now the /SSO end-point return the expected Cookies; However, they are sent without expiry date which means they are not persistence.

Looking into keycloak implementation of AuthenticationManager.java (Line 664) you can see the following code
if (session != null && session.isRememberMe()) {
maxAge = realm.getSsoSessionMaxLifespanRememberMe() > 0 ? realm.getSsoSessionMaxLifespanRememberMe() : realm.getSsoSessionMaxLifespan();
}
Did you have same issue? Any suggestion how can I change cookies lifespan?

We don’t use “Remember Me” and I currently don’t know how Session#rememberMe can be set to true besides by the user checking the “Remember me” checkbox on the login page.

In our use case, we set the SSO cookies with an access token obtained through token exchange and direct access grants, and I have no idea if it is possible to set rememberMe when a session is created this way and unfortunately I don’t have the chance to try and find out at the moment :slightly_frowning_face:
Of course I’d be interested if you find out something!

Could you share how you handle CORS? I run in the same issue and cant figure it out :frowning:

Nevermind, the problem was that no storageProviders are found and hence the user is always null.
We now just use the following line to obtain the user:

UserModel user = keycloakSession.users().getUserById(token.getSubject(), realm);

And this is how we handle Cors using org.keycloak.services.resources.Cors:

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    @Path("/sso")
    public Response sso(@Context final HttpRequest request) {
      // ... stuff to set the cookie ...
      Cors cors = Cors.add(request, Response.noContent()).auth()
                .allowedMethods("GET")
                .allowedOrigins(token)
                .auth().exposedHeaders();
        return cors.build();

Also, we needed to add an @OPTIONS endpoint:

    @OPTIONS
    @Path("/sso")
    public Response preflight(@Context final HttpRequest request) {
        return Cors.add(request, Response.ok()).auth().preflight()
                .allowAllOrigins()
                .allowedMethods("GET", "OPTIONS").build();
    }

So, now we are also have the issue with the rememberMe / session-dropping on page reload.

2 Likes

I tried copying the AuthenticationManager.createLoginCookie(...) to set maxAge but the cookies are not set anyway :frowning: The response header looks fine, but they do not show up in devtools > Application > Cookies.

image

I was missing the credentials: 'include' flag for the fetch call on the frontend. For me it’s working now (including a persistent session on page refresh and without hacking a maxAge for the cookies).

1 Like

Thank you Tikko for the suggestion, It works!
Regarding CORS I tried to implement your approach however I’m missing the module dependencies. Here’s my current module addition command.

module add  ... --dependencies=org.keycloak.keycloak-core,org.keycloak.keycloak-server-spi,org.keycloak.keycloak-server-spi-private,javax.ws.rs.api,org.keycloak.keycloak-services

I believe the missing one is for import org.jboss.resteasy.spi.HttpRequest; library.
Thank you in advance for any hint…

org.jboss.resteasy.resteasy-jaxrs was the missing dependency. :slight_smile:

Hi all,

Thanks for your solution. It works ! I use it to establish a session in a embedded browser (javafx) using access token previously obtained by keycloak desktop adapter and authorization grant flow.

But, is there any security issues implied by this implementation ?

@gitdode Thank you for your answer :slight_smile: I try to set up your solution. But when I try to insert the resteasy dependency, I get the following error:

ERROR [org.keycloak.services.error.KeycloakErrorHandler] (default task-1) Uncaught server error: java.lang.NoClassDefFoundError: org / keycloak / common / util / Resteasy.

This is my dependency list:

I tried to import the module using the following command:

module add … --dependencies=org.keycloak.keycloak-core,org.keycloak.keycloak-server-spi,org.keycloak.keycloak-server-spi-private,javax.ws.rs.api,org.keycloak.keycloak-services,org.jboss.resteasy.resteasy-jaxrs

Unfortunately my SPI is not displayed in the admin. But if I add my .jar in jboss/keycloak/standalone/deployments, then I see my SPI in the admin. But with the error mentioned above.

I am new to the Java/Keycloak world. I am happy for any help.

@solonik here’s the depencies that I have in my project (besides some specific stuff, test dependencies and so on), hope it is of any help:

    <depencencies>
    <!-- JEE dependencies -->
    <dependency>
        <groupId>javax</groupId>
        <artifactId>javaee-api</artifactId>
        <version>7.0</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.jboss.ejb3</groupId>
        <artifactId>jboss-ejb3-ext-api</artifactId>
        <version>2.2.0.Final</version>
        <scope>provided</scope>
    </dependency>

    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.7.7</version>
        <scope>provided</scope>
    </dependency>

    <!-- Keycloak dependencies -->
    <dependency>
        <groupId>org.keycloak</groupId>
        <artifactId>keycloak-core</artifactId>
        <version>${version.keycloak}</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.keycloak</groupId>
        <artifactId>keycloak-common</artifactId>
        <version>${version.keycloak}</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.keycloak</groupId>
        <artifactId>keycloak-model-infinispan</artifactId>
        <version>${version.keycloak}</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.keycloak</groupId>
        <artifactId>keycloak-server-spi</artifactId>
        <version>${version.keycloak}</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.keycloak</groupId>
        <artifactId>keycloak-server-spi-private</artifactId>
        <version>${version.keycloak}</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.keycloak</groupId>
        <artifactId>keycloak-services</artifactId>
        <version>${version.keycloak}</version>
        <scope>provided</scope>
    </dependency>
</dependencies>
1 Like

Is there a way to proceed with the steps mentioned in the link using keycloak-js?