hasura / graphql-engine

Blazing fast, instant realtime GraphQL APIs on your DB with fine grained access control, also trigger webhooks on database events.
https://hasura.io
Apache License 2.0
31.16k stars 2.76k forks source link

Keycloack Identity and Access Management #1779

Closed lobosan closed 5 years ago

lobosan commented 5 years ago

Hi guys, can you please create a similar tutorial to this one: Firebase + Hasura, but based on Keycloak + Hasura?

Also if you could deploy it on OpenShift to showcase an open source fullstack example running in a production environment it would be a dream come true, specially if you add to the stack an API Gateway.

All the best and thanks for considering my proposal.

0xHexE commented 5 years ago

Hey, @lobosan I have created a small utility which connects the hasura and keycloak. https://github.com/httpsOmkar/keycloak-hasura-connector

mnlbox commented 5 years ago

@httpsOmkar it's awesome news. Can you tell me your username in discord?

0xHexE commented 5 years ago

Hello @mnlbox My discord id is omkar#0915

lobosan commented 5 years ago

Hi @httpsOmkar you are awesome thanks for your great support :)

marionschleifer commented 5 years ago

@httpsOmkar thank you for this contribution 🎉 I'm closing this issue now. If any of you would like to add something to it, feel free to re-open it 🙂

webdeb commented 4 years ago

Just wanted to add my 2 cents to this. Since keycloak is an awesome selfhosted auth server. There are ways to configure keycloak directly, without the necessity of plugging a separate webhook service between.

keycloak has this feature of script mappers, you can basically write JS inside the configuration to put additional hasura claims into the JWT token, just like with auth0 rules:

I think its self explainable

Bildschirmfoto 2019-12-26 um 16 44 55
Nico-L commented 4 years ago

Hello, I'm looking to setup hasura with keycloak. I entered the script mapper and then I'm trying to configure the JWT mode and trying to set HASURA_GRAPHQL_JWT_SECRE. The json config is composed of the type and the jkw url of the my keycloak server. I received the following error:

 Error parsing JWK from url (https://keycloakserver/auth/realms/<my-realm>/protocol/openid-connect/certs): Error in $.keys[2]: expected 66 octets, found 65

I really don't know how to fix this. My guess was a problem of criptography but I tried every accepted configuration without any success.

Thanks

webdeb commented 4 years ago

@Nico-L you have to provide the json as a string

HASURA_GRAPHQL_JWT_SECRET: '{ "jwk_url": "http://keycloak:8080/auth/realms/<your-realm>/protocol/openid-connect/certs", "type": "HS256" }'
Nico-L commented 4 years ago

@webdeb that was a quick answer! A string is required if put the config directly in the docker-compose file, but I have to supply the json object if I use env variables. Does it make sense to you?

Anyway, the problem was in the realm keys definition: I had a array of 3 keys, two of them wasn't supported by Hasura. I just kept the RS256 key and Hasura launched without error.

Everything seems OK, even though I expected the jwt-secret to appear in the Request Headers of the console. It's not there, but the jwt token is decoded so I guess it's OK.

Now, Hasura requested both x-hasura-default-role and x-hasura-allowed-roles. This last one is a bit tricky as if you just put a javascript group inside the json claim of the script wrapper, it is traducted as a json object:

"x-hasura-allowed-roles": ["user", "admin"]

translates into in the token:

x-hasura-allowed-roles": {
"0": "user",
"1": "admin"
}

which is not validated by Hasura. You have define a java array before (from stackoverflow) and pass it to the claim. So the working script mapper is the following:

var allowedGroups = java.lang.reflect.Array.newInstance(java.lang.String.class, 2);
allowedGroups[0] = "user"
allowedGroups[1] = "admin"
//insert your code here...
token.setOtherClaims("https://hasura.io/jwt/claims" , {
    "x-hasura-role": "user",
    "x-hasura-default-role": "user",
    "x-hasura-allowed-roles": allowedGroups,
    "x-hasura-user-id": user.id
})

Then the token is validated. Thanks

webdeb commented 4 years ago

@Nico-L had this problem as well, check out my gist with a mapper: https://gist.github.com/webdeb/d8a99df9023f01b78e3e8ff580abe10b


Basically, you have to translate the js array into a Java List

var roles = [];
for each (var role in user.getRoleMappings()) roles.push(role.getName());
token.setOtherClaims("https://hasura.io/jwt/claims", {
    "x-hasura-user-id": user.getId(),
    "x-hasura-allowed-roles": Java.to(roles, "java.lang.String[]"),
    "x-hasura-default-role": "user",
});

So, you can just add roles from your realm, to your users and put them into allowed roles, don't need to code it every time you add a role

webdeb commented 4 years ago

A side-note on "x-hasura-role" don't put it into the JWT, it's better to provide it via the headers, so you can use different roles (of allowed) for different tasks.

Nico-L commented 4 years ago

@webdeb I wish I found your example sooner, I spend a bit of a time looking for the script mapper before realizing that I had to add the -Dkeycloak.profile.feature.upload_scripts=enabled command :D

Great tips, I'll modify my script accordingly. Thank you

jaekook-neonesia commented 4 years ago

Another Approach..

Rigel772 commented 8 months ago

There is nice tutorial for newest Keycloak 23.0.6 for anyone interested: https://dev.to/mrtousif/hasura-and-keycloak-integration-with-nestjs-server-without-using-passportjs-4kjh