I have been trying to use next-auth with this keycloak-passport Strategy. (I did have to modify the strategy's name to be lowercase to be able to test it out)
I can log in no problem and it creates a session. Only problem is, getProfile() doesn't seem to fire at all so the session just contains the csrfSecret but no user. Keycloak recognises I'm already logged in when trying to log in.
Have been trying to debug through what could be happening but couldn't get to the bottom of it. Any direction on what might be the issue would be great. If I get it working would be happy to submit some documentation on it.
I haven't used that strategy before, but in theory they should all work (of course the oAuth spec is a bit vague on the details of profiles, so reality is different).
The getProfile() function should be fired on line 77 of next-auth/src/passport-strategies.js, and passed a profile object as returned by the remote service (even if it's null).
Can you see if your getProfile() function in next-auth.providers.js fires (e.g. console.log) and the 'profile' object in your is null or contains anything?
To debug you could hard code a user object response in getProfile() that looks something like this to see if that helps.
javascript
getProfile(profile) {
console.log("Got profile from keycloak: ", profile)
return {
id: "123",
name: "J Smith"
email: "[email protected]"
}
}
The fields you need are 'id', 'name' and email. If you don't get an email address from the service (e.g. sites like Twitter don't return it unless you explicitly request it) you can use something like ${profile.id}@localdomain.com.
Another thing to watch for is some providers require explicit options, like scope, e.g.:
javascript
providerOptions: {
scope: ['profile', 'email']
},
Next.js refreshes the output on the console so can be handy to do something like npm run dev > debug.log | tail -f debug.log to log the output for debugging.
I've just looked at #38 raised by @mBeierl and I think the same issue impacts this strategy.
https://github.com/exlinc/keycloak-passport
It passes a different list of arguments in the callback (accessToken, refreshToken, profile, done) but next-auth is expecting the strategy to return (req, accessToken, refreshToken, _profile, next).
I thought the method signature for this callback was standardised in all strategies (because it works this way in Google, Facebook and Twitter and a few others) but I guess not in the wild!
It's easy to hack for a specific strategy (e.g. fork the strategy and change what it returns) as a workaround but I'm not sure what the best way to handle different responses in strategies like this is (as there is already too much complexity to configuration and I should be focusing on reducing it :-).
I'll have a think and see what we can do!
Thanks for looking into it π
Yeah trying that snippet in the getProfile and no joy. I am testing this out in your example so added a console to line 76 of next-auth/src/passport-strategies.js and it doesn't get fired. Based on your comment I'm assuming this is due to the difference in method signatures?
It looks like it uses the library https://github.com/jaredhanson/passport-oauth2 which is what's returning the different signature.
I'm not sure how you can solve this compatibility issue easily, with maybe having your own version of keycloak-passport. :-(
The keycloak-passport strategy doesn't seem to do too much, I wonder if a generic oAuth 2 module for Passport (other than err passport-oauth2β¦ there seem to be a few at least!) might work in this case?
I'm not sure how you can solve this compatibility issue easily, with maybe having your own version of keycloak-passport. :-(
Lookinking more likely I might just have go this route π’
The keycloak-passport strategy doesn't seem to do too much, I wonder if a generic oAuth 2 module for Passport (other than err passport-oauth2β¦ there seem to be a few at least!) might work in this case?
Not 100% sure by what you mean here π€
Hmm looking at the options that may not be as easy as I thought.
Can you paste in your config for the provider from next-auth/src/passport-strategies.js?
I think I have a fix I can suggest.
Basically, in your strategyOptions add passReqToCallback with a value of true and it should work!
javascript
strategyOptions: {
/* other options */
passReqToCallback: true
},
It seems the underlying module keycloak-passport uses respects this option and will return the method signature you need so will be compatible. :-)
Oh wait boo, I just realised next-auth already does this for you! Damn. Nevermind that then.
So err sorry something else is going on with the service. :-(
keycloak-passport uses passport-oauth2 under the hood and there are a bunch of open issues about callbacks not firing there. I'm not sure what's going on or how you can fix it, as it seems like it's not something next-auth can fix. :-/
I would maybe as the maintainer of passport-keycloak if they have any tips.
providers.push({
providerName: 'keycloak',
Strategy: KeycloakStrategy,
strategyOptions: {
host: 'https://www.site.com',
authorizationURL:
'https://www.site.com/auth/realms/site/protocol/openid-connect/auth',
tokenURL:
'https://www.site.com/auth/realms/site/protocol/openid-connect/token',
userInfoURL:
'https://www.site.com/auth/realms/site/protocol/openid-connect/userinfo',
realm: 'realm',
clientID: 'web-client',
clientSecret: 'SECRET',
callbackURL: '/auth/callback',
passReqToCallback: true
},
getProfile(profile) {
console.log('Got profile from keycloak: ', profile);
return {
id: '123',
name: 'J Smith',
email: '[email protected]'
};
}
});
This is my config. No joy with the suggestion π
Thanks for the help. I will open an issue over @passport-keycloak. If I make any progress, I will update this issue.
Okies, so you can remove passReqToCallback as it already adds it, but one last thing to try:
1) Remove callbackURL and let it be set automatically, as the current value (/auth/callback) isn't right.
2) If you need to set it manually, set it to /auth/oauth/keycloak/callback (you can also specify your servers protocol and hostname, name like: http://localhost:300/auth/oauth/keycloak/callback)
(The keycloak bit in the callback URL isn't special, it just needs to match whatever you have put in as the providerName, which is currently set to keycloak.)
π Nice one
So removing the callback and setting my host to http://localhost:300/auth/oauth/keycloak/callback has moved me along. I can now log in and it returns the correct profile. It also updates the session as expected.
Not sure if this is related but if I click log out I now get this screen if trying to log in again:

Hmm no that should not be related, but I'm not sure what's causing that.
You might want to close down your browser, stop and start the service again and try and replicate it.
In development mode, Next.js does hot-reloading and caches pages in Service Workers and browser behaviour can get weird if you stop and start things and the only way to clear it out is to close and re-open the browser. Both those things (which only happen in development mode on Next.js projects) cause weird page refreshes.
PS: Thanks for reminding me a I need to fix a typo on that that example error page (just pushed that).
Tried it in a new browser in production mode and no joy, still not allowing me to log in after logging out. Interestingly if I stop and start the server it authenticates me when I click sign in, so looks like it's not actually logging me out correctly.
But as far as the original issue goes I think we can close it? I will do a bit more digging on this logging out issue and see can I get to the bottom of it. It seems like I am not actually being logged out.
π I'm terrible for typos so didn't even notice
Thanks for all the help with this by the way! πͺ
You welcome! And great yes, lets close this off so it's easy for anyone to follow if they find it when Googling in case they have the same thing. :-) Happy to help with the separate log out issue!
The logout button code should be pretty simple, so hopefully won't involve too much debugging.
You might want to take look at the handleSignoutSubmit() function in the nextjs-starter project if it helps. You absolutely don't need to set the cookie like it does, but it can be nice user behaviour (as it signs them out but keeps them on the same page).
Did you solve this or have a repo that has a basic implementation of nextjs + keycloak?