Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sign-In after Sign-out doesn't ask for username after password with Keycloak #6941

Closed
1 task done
rakeshkalra1983 opened this issue Jan 3, 2018 · 34 comments
Closed
1 task done

Comments

@rakeshkalra1983
Copy link

Overview of the issue

I created Jhipster app with OIDC (Keycloak) integration, I signed in to application with admin account, then I clicked signed-out. Now when I click sign-in again, application doesn't ask me for username password, but directly sign me in as admin.

Motivation for or Use Case

If I want to sign-out and want to sign-in as different user, I am failing to do so.

Reproduce the error

Steps mentioned in overview of issue.

JHipster Version(s)

4.13.1

JHipster configuration

{
"generator-jhipster": {
"promptValues": {
"packageName": "com.fya"
},
"jhipsterVersion": "4.13.1",
"baseName": "fya",
"packageName": "com.fya",
"packageFolder": "com/fya",
"serverPort": "8080",
"authenticationType": "oauth2",
"cacheProvider": "ehcache",
"enableHibernateCache": false,
"clusteredHttpSession": false,
"websocket": false,
"databaseType": "mongodb",
"devDatabaseType": "mongodb",
"prodDatabaseType": "mongodb",
"searchEngine": false,
"messageBroker": false,
"serviceDiscoveryType": false,
"buildTool": "maven",
"enableSocialSignIn": false,
"enableSwaggerCodegen": false,
"clientFramework": "angularX",
"useSass": false,
"clientPackageManager": "yarn",
"applicationType": "monolith",
"testFrameworks": [],
"jhiPrefix": "jhi",
"enableTranslation": false
}
}

Browsers and Operating System

Safari, MacOS

  • Checking this box is mandatory (this is just to show you read everything)
@pascalgrimaud
Copy link
Member

Maybe the same ticket ?
#6555

@javaScientist
Copy link

I can confirm the behavior. I'm having the same problem. I would expect that if i click on logout, i will logout from all applications and the keycloak server.
I would expect the behavior as with Google and Youtube. When i login to google, i am automaticly logged in to youtube.
And when I sign out of Google, I'm also logged out of youtube.
Further more it is complicated when we are in development mode and we use two different users for testing. It is not possible to change user.

It seams that #6555 is an similar ticket. But this ticket is closed and the issue is still there.
Can someone else confirm this or is it really the desired behavior?

@mraible
Copy link
Contributor

mraible commented Jan 25, 2018

Logging out of the IpP (Keycloak in this instance) is not the nature of single-sign on. When you log out of an app, changes are you don't want to logout of your IdP. If you logged into an application with Facebook, you wouldn't want logging out of that app to log you out of Facebook, would you?

Yes, it can be a pain for testing. That's why I recommend using incognito mode.

@mraible
Copy link
Contributor

mraible commented Jan 25, 2018

@javaScientist You might be able to use this solution to create a LogoutHandler that logs you out of the IdP as well.

@javaScientist
Copy link

@mraible Thank you for your feedback . I will try to implement a custom LogoutHandler .

@stieler-it
Copy link
Contributor

Our behaviour is a little different:

  1. Login as user 1
  2. Logout
  3. Click on Login again

Expected: The user is already signed in as the Keycloak login is still active
Actual: Keycloak shows a login form. If you try to sign in as another user, it says "You are already authenticated as different user 'ref711ma' in this session. Please logout first." There is no logout button, though.

Did we break the configuration somehow or does someone else experience the same behavior?

@stieler-it
Copy link
Contributor

Ok sorry, I tried it with a vanilla keycloak - without our configuration changes the behavior is like described here before.

@Filson14
Copy link

Filson14 commented Mar 12, 2018

@stieler-it have You noticed which config changes could be responsible for that behaviour? I deal with the same scenario as You described (but it's nondeterministic; sometimes you can log in as another user, sometimes you don't). Nethertheless, I think I should try custom logout handler to log user out from app AND keycloak.

@stieler-it
Copy link
Contributor

We did not spend time investigating which (Keycloak?) configuration was responsible for our behaviour. I am pretty sure it was deterministic, though. And regarding the logout handler: We implemented ours in the frontend, so the browsers calls Keycloak's logout URL after app logout, which is probably not a very secure idea but it works for us.

@Filson14
Copy link

Thanks for your reply. I use (mainly) logout method from keycloak js adapter (which redirect to logout URL; as recommended). But sometimes the keycloak session is still active and then I have the issue as you have described.

@deepu105
Copy link
Member

Sorry to spam you today @mraible, just trying to clean up issues. Does any of your recent PRs address this?

@mraible
Copy link
Contributor

mraible commented Mar 16, 2018

No. My comment is still valid.

@jgrandja Any chance that Spring Security OAuth will provide global logout as a feature in the future?

@jgrandja
Copy link

@mraible It's a feature we can consider for the new OAuth support we're building in Spring Security 5.x.

Just to clarify, are you referring to OpenID Connect Back-Channel Logout 1.0?

@mraible
Copy link
Contributor

mraible commented Mar 16, 2018

I'm not sure what it's called, but I'm guessing it'd be something that uses the revocation_endpoint or end_session_endpoint from ./well-known/openid-configuration. Here's what those look like from my Okta tenant: https://dev-158606.oktapreview.com/oauth2/default/.well-known/openid-configuration

@jgrandja
Copy link

Gotchya. As mentioned, it's a feature we can consider implementing later on. There's just higher priority items going on now as we're heads down on the new Resource Server support and also adding more to Client support for 5.1

@mraible
Copy link
Contributor

mraible commented Jul 16, 2018

I recently learned that Okta doesn’t support OIDC Back-Channel Logout. I did figure out how to do it using a redirect on the frontend.

@jdubois jdubois added the $100 https://www.jhipster.tech/bug-bounties/ label Aug 9, 2018
@jdubois
Copy link
Member

jdubois commented Aug 31, 2018

I understand the issue (we have the same for a customer, and did a custom solution), but I'm closing this as:

  • @mraible already answered why this is the case today. To me this is a limitation on OIDC, or a missing feature.
  • There are some workaround like the one @mraible gives, but they are specific to a provider. At the moment, we do not do anything specific per provider, as the goal is to be neutral and work with as many providers as possible. I would love to have this working with Google, for example.
  • Hopefully this will be solved with the next release of Spring Security OAuth2, like @jgrandja says, but that's a migration we will do once it's released, and it will be a specific ticket (with probably a lot of work!)

Besides, this has been opened for 8 months, and I even gave a $100 bounty on this, and this doesn't seem to interest any contributor.

@jdubois jdubois closed this as completed Aug 31, 2018
@jdubois jdubois removed the $100 https://www.jhipster.tech/bug-bounties/ label Aug 31, 2018
@jdubois jdubois added this to the 5.3.0 milestone Sep 3, 2018
@yelhouti
Copy link
Contributor

Hey @jdubois :)

could you put the bounty back? I fixed it...

Thanks in advance

@deepu105
Copy link
Member

@yelhouti could you link the PR where you fixed it? I didn't find any

@jdubois
Copy link
Member

jdubois commented Sep 23, 2018

@yelhouti it depends on the fix as this isn't a trivial issue, can you tell us at least what you intend to do?

@yelhouti
Copy link
Contributor

@jdubois , @deepu105
I didn't make a PR, my fix is working locally but would need some rewrite to work for all IdPs.

Basically, what I do is use GET instead of POST for the jhipster api/logout endpoint and change the logoutSuccessHandler to do a redirect on the IdP URL, which in most IdPs (keycloak, Okta) the same as the user info endpoint (XXX/userinfo => XXX/logout).
I didn't find in the oauth2/oidc spec an endpoint for the logout feature (and don't I think there is one, since it's more of SSO feature than a oauth2 one).

So the cleanest way for me is to specify in the application.yml a new entry:
oauth2.slo.url and oauth2.slo.redirect-uri-query-param and use them for the redirect mentioned earlier.

@stieler-it
Copy link
Contributor

Like @mraible already explained, I'm not sure if logging out should be the default behavior of JHipster generated apps. If you integrate your app into an existing SSO infrastructure in your company you probably don't want to be auto-logged out there. Thus, I think we don't need a fix here but a new feature so the developer can decide what happens on logout. If the user can't do an actual logout, I can also imagine it would be best to remove the logout menu item.

@jdubois
Copy link
Member

jdubois commented Sep 24, 2018

OK so following @stieler-it advice I indeed think we should not change the default behavior. I understand many people want this (and I have a client who does), but that would be confusing for all other people who expect the "normal" behavior.

@yelhouti how about contributing a tip at https://www.jhipster.tech/tips/ ? This would indeed be helpful for many people

@maznag
Copy link
Contributor

maznag commented Sep 24, 2018

For OKTA, as @mraible already explained in one of his tutorials Logout with OKTA we can modify the logout() method to send a logout URL and the ID token back to the client as follow (it works well for okta but I haven't tested it for Keycloak).

  • AccountResource Api
   private final UserService userService;
   private final UserInfoRestTemplateFactory templateFactory;

    @Value("${security.oauth2.client.access-token-uri}")
    String accessTokenUri;

    public AccountResource(UserService userService, UserInfoRestTemplateFactory templateFactory) {
        this.userService = userService;
        this.templateFactory = templateFactory;
    }
    /**
     * GET /api/logout : logout the current user.
     *
     * @param request http request (HttpServletRequest)
     * @return authentication the Authentication object
     */
    @PostMapping("/logout")
    public ResponseEntity logout(HttpServletRequest request, Authentication authentication) {
        log.debug("REST request to logout User : {}", authentication);
        // send logout URL to client so they can initiate logout - doesn't work from the server side

        OAuth2RestTemplate oauth2RestTemplate = this.templateFactory.getUserInfoRestTemplate();
        String idToken = (String) oauth2RestTemplate.getAccessToken().getAdditionalInformation().get("id_token");

        // logout URI can be derived from accessTokenUri
        String logoutUrl = accessTokenUri.replace("token", "logout");

        Map logoutDetails = new HashMap<>();
        logoutDetails.put("logoutUrl", logoutUrl);
        logoutDetails.put("idToken", idToken);
        request.getSession(false).invalidate();
        return ResponseEntity.ok().body(logoutDetails);
    }
  • Angular Service account.service.ts
    // logout from the server
    logout() {
        this.logoutFromServer().subscribe((response: any) => {
            const logoutUrl = response.body ? response.body.logoutUrl : response.logoutUrl;
            const idToken = response.body ? response.body.idToken : response.idToken;
            if (logoutUrl && idToken) {
                location.href = logoutUrl + '?id_token_hint=' + idToken + '&post_logout_redirect_uri=' + window.location.origin;
            }
        });
    }

    private logoutFromServer(): Observable {
        return this.http.post(SERVER_API_URL + 'api/logout', {}, { observe: 'response' });
    }

@yelhouti
Copy link
Contributor

@jdubois I can definitely do that, and I totally agree that when using OAuth2 this should be the default behavior.
@maznag what you mentioned definitely works and it was my first solution until I decided to use standard redirect and use get like in login instead of post.

@jdubois @deepu105 I want to mention that using OAuth2 instead of OIdC for authentication (instead of authorization) is wrong, and when external/malicious clients exist allows then to impersonate any user. In must simple app cases this not a problem but in big companies using the same keycloak realm for other purposes, this could create a serious vulnerability threat.
I also understand that with spring 1.X.X doesn have support OOTB (I think it is the case now with Spring 2).

I can help work on that but unfortunately I don't have the time/budget to do all that part on my own.

@mraible
Copy link
Contributor

mraible commented Sep 24, 2018 via email

@yelhouti
Copy link
Contributor

@mraible I just rechecked the code, the part responsible for checking the token is:

OAuth2Authentication result = tokenServices.loadAuthentication(accessToken.getValue());

in the SSOConfig,
which in turn use the OAuth2 userinfo endpoint that checks that token is valid. the endpoint doesn't/can't check the audience field since it doesn't know against what to check it (and it's not it's job).
the endpoint returns a json without this audience info and the info is lost and never checked after that.

So unless you can show me where is this field checked (and according to OIDC spec it should be) I maintain my point that this is an issue.

I can link to the spec part if you need that, but I think you are familiar with it.

@mraible
Copy link
Contributor

mraible commented Sep 24, 2018 via email

@yelhouti
Copy link
Contributor

yelhouti commented Sep 24, 2018

@mraible the part of Spring security we are using has implmented OAuth2 not OIDC. It's implemted correctly for the authorization use case, and we are using it for the authentication use case.
PS: this is exactly what OIDC is supposed to fix.
EDIT: we are using spring security the wrong way.
EDIT2: by the way /tokeninfo is an OAuth2 endpoint, explaination and RFC in this link: https://www.oauth.com/oauth2-servers/token-introspection-endpoint/
it's also a IODC endpoint since OIDC is a superset of OAuth2

@mraible
Copy link
Contributor

mraible commented Sep 24, 2018

A PR to use it the right way is most welcome!

@yelhouti
Copy link
Contributor

Unfortunately, I just don't have time for that these days, as soon as I can I will do it.

@darkguy2008
Copy link

Any news on this? I don't think this should be closed, I'm a new keycloak user and I'm facing this after integrating it with Seafile and Outline. Logging out from those apps don't seem to log out from keycloak, and I get that stupid error.

I mean, it would be just great if the page would have a "Okay, log me out" link/button or something, instead, we're locked in without a way to sanely log out. This kinda sucks.

@mraible
Copy link
Contributor

mraible commented Oct 2, 2021

@darkguy2008 A JHipster app will log you out as expected these days. Please don't comment on an issue that is closed and has nothing to do with JHipster.

@darkguy2008
Copy link

@darkguy2008 A JHipster app will log you out as expected these days. Please don't comment on an issue that is closed and has nothing to do with JHipster.

Oh whoops, my bad, I commented thinking this was the Keycloak repo, or part of the organization, sorry!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests