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

Add keycloak SSO #5711

Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
ab86419
Add keycloak SSO
paulbauriegel Nov 22, 2024
8fd3b3b
Merge branch 'refactor/argilla-server/better-oauth2-integration' into…
paulbauriegel Nov 26, 2024
41bf238
Merge branch 'refactor/argilla-server/better-oauth2-integration' into…
frascuchon Dec 2, 2024
03b10e7
chore: Create keycloack backend
frascuchon Dec 2, 2024
7f319d2
Update docs for new backend
paulbauriegel Dec 2, 2024
0da655e
Merge branch 'refactor/argilla-server/better-oauth2-integration' into…
frascuchon Dec 3, 2024
bf2a0f6
feat: Configure role and workspaces from realm access roles
frascuchon Dec 3, 2024
174b9b9
Update User role after login
paulbauriegel Jan 16, 2025
8cddf2f
Update Keycloak Docs w. Mapper
paulbauriegel Jan 16, 2025
a474061
Use always the max rights role from the realm roles
paulbauriegel Jan 16, 2025
a25938e
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jan 16, 2025
c3c20eb
Add last_name to userinfo.py
paulbauriegel Jan 16, 2025
55c64b3
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jan 16, 2025
58bb93a
Update oauth2 handler to update workspaces if needed
paulbauriegel Jan 16, 2025
bc1084a
Merge branch 'refactor/argilla-server/better-oauth2-integration' into…
paulbauriegel Jan 22, 2025
7898ebb
Using flag to sync user from oauth info
frascuchon Jan 28, 2025
38ee8b7
Merge branch 'refactor/argilla-server/better-oauth2-integration' into…
frascuchon Jan 28, 2025
42fc36e
Update argilla-server/src/argilla_server/security/authentication/user…
paulbauriegel Jan 28, 2025
8395cb9
Update argilla-server/src/argilla_server/security/authentication/user…
paulbauriegel Jan 28, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
164 changes: 164 additions & 0 deletions argilla-frontend/components/features/login/components/KeycloakLogo.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
<template>
<!--https://github.com/keycloak/keycloak-misc/blob/main/logo/icon.svg-->
<svg
width="256"
height="256"
viewBox="0 0 44.216 39.861"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="m88.61 138.456 5.716-9.865 23.018-.004 5.686 9.965.007 19.932-5.691 9.957-23.012.008-5.782-9.965z"
style="
display: inline;
fill: #4d4d4d;
fill-opacity: 1;
stroke-width: 0.264583;
"
transform="translate(-82.815 -128.588)"
/>
<path
d="M88.552 158.481h10.375l-5.699-10.041 4.634-9.982-9.252-.002-5.795 10.065"
style="
fill: #ededed;
fill-opacity: 1;
fill-rule: nonzero;
stroke: none;
stroke-width: 0.330729;
"
transform="translate(-82.815 -128.588)"
/>
<path
d="M102.073 158.481h7.582l6.706-9.773-6.589-10.156h-8.921l-5.373 9.814z"
style="
fill: #e0e0e0;
fill-opacity: 1;
fill-rule: nonzero;
stroke: none;
stroke-width: 0.330729;
"
transform="translate(-82.815 -128.588)"
/>
<path
d="m82.815 148.52 5.738 9.964h10.374l-5.636-9.93z"
style="
fill: #acacac;
fill-opacity: 1;
fill-rule: nonzero;
stroke: none;
stroke-width: 0.330729;
"
transform="translate(-82.815 -128.588)"
/>
<path
d="m95.589 148.522 6.484 9.963h7.582l6.601-9.959z"
style="
fill: #9e9e9e;
fill-opacity: 1;
fill-rule: nonzero;
stroke: none;
stroke-width: 0.330729;
"
transform="translate(-82.815 -128.588)"
/>
<path
d="m98.157 148.529-1.958.569-1.877-.572 7.667-13.288 1.918 3.316"
style="
fill: #00b8e3;
fill-opacity: 1;
fill-rule: nonzero;
stroke: none;
stroke-width: 0.330729;
"
transform="translate(-82.815 -128.588)"
/>
<path
d="m103.9 158.482-1.909 3.332-5.093-5.487-2.58-7.797v-.004h3.838"
style="
fill: #33c6e9;
fill-opacity: 1;
fill-rule: nonzero;
stroke: none;
stroke-width: 0.330729;
"
transform="translate(-82.815 -128.588)"
/>
<path
d="M94.322 148.526h-.003v.003l-1.918 3.322-1.925-3.307 1.952-3.386 5.728-9.92h3.834"
style="
fill: #008aaa;
fill-opacity: 1;
fill-rule: nonzero;
stroke: none;
stroke-width: 0.330729;
"
transform="translate(-82.815 -128.588)"
/>
<path
d="M115.42 158.481h11.611l-.007-19.93h-11.605z"
style="
fill: #d4d4d4;
fill-opacity: 1;
fill-rule: nonzero;
stroke: none;
stroke-width: 0.330729;
"
transform="translate(-82.815 -128.588)"
/>
<path
d="M115.42 148.554v9.93h11.59v-9.93z"
style="
fill: #919191;
fill-opacity: 1;
fill-rule: nonzero;
stroke: none;
stroke-width: 0.330729;
"
transform="translate(-82.815 -128.588)"
/>
<path
d="M101.992 161.817h-3.836l-5.755-9.966 1.918-3.321z"
style="
fill: #00b8e3;
fill-opacity: 1;
fill-rule: nonzero;
stroke: none;
stroke-width: 0.330729;
"
transform="translate(-82.815 -128.588)"
/>
<path
d="m117.333 148.526-7.669 13.289c-.705-1.036-1.913-3.331-1.913-3.331l5.753-9.959z"
style="
fill: #008aaa;
fill-opacity: 1;
fill-rule: nonzero;
stroke: none;
stroke-width: 0.330729;
"
transform="translate(-82.815 -128.588)"
/>
<path
d="m113.495 161.815-3.831-.001 7.67-13.288 1.917-3.317 1.921 3.34m-3.839-.023h-3.828l-5.755-9.973 1.905-3.314 4.658 5.922z"
style="
fill: #00b8e3;
fill-opacity: 1;
fill-rule: nonzero;
stroke: none;
stroke-width: 0.330729;
"
transform="translate(-82.815 -128.588)"
/>
<path
d="M119.25 145.205v.003l-1.917 3.318-7.677-13.286 3.841.002z"
style="
fill: #33c6e9;
fill-opacity: 1;
fill-rule: nonzero;
stroke: none;
stroke-width: 0.330729;
"
transform="translate(-82.815 -128.588)"
/>
</svg>
</template>
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
<template>
<BaseButton class="sign-in-button" @click="$emit('click')">
<KeycloakLogo v-if="provider === 'keycloak'" />
{{ signinText }}
</BaseButton>
</template>

<script>
import KeycloakLogo from "./KeycloakLogo.vue";

export default {
name: "OAuthLoginButton",
components: {
KeycloakLogo,
},
props: {
provider: {
type: String,
Expand Down
2 changes: 1 addition & 1 deletion argilla-frontend/translation/de.js
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ export default {
button: {
ignore_and_continue: "Ignorieren und fortfahren",
login: "Anmelden",
signin_with_provider: "Anmeldung bei {provider} starten",
signin_with_provider: "Mit {provider} anmelden",
"hf-login": "Mit Hugging Face anmelden",
sign_in_with_username: "Mit Benutzername anmelden",
cancel: "Abbrechen",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ def load_supported_backends(extra_backends: list = None) -> Dict[str, Type[BaseO
"argilla_server.security.authentication.oauth2._backends.HuggingfaceOpenId",
"social_core.backends.github.GithubOAuth2",
"social_core.backends.google.GoogleOAuth2",
"social_core.backends.keycloak.KeycloakOAuth2",
paulbauriegel marked this conversation as resolved.
Show resolved Hide resolved
]

if extra_backends:
Expand Down
152 changes: 152 additions & 0 deletions argilla/docs/reference/argilla-server/sso_keycloak.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
# SSO Integration Keycloak

## Set-up Keycloak

To test this run a test version of Keycloak in Docker:

```bash
docker run -p 8080:8080 -e KC_BOOTSTRAP_ADMIN_USERNAME=admin -e KC_BOOTSTRAP_ADMIN_PASSWORD=admin quay.io/keycloak/keycloak:26.0.5 start-dev
```

General steps:
1. create a new realm and a new client to use with Argilla.
2. The client should expose the client audience via userinfo.
3. After that add the users you want to have access to argilla.

The script below should do all of that for you to test. It needs one python dependency you can install with `pip install python-keycloak`.


```python
from keycloak import KeycloakAdmin
from keycloak import KeycloakOpenIDConnection
from keycloak import KeycloakOpenID

keycloak_connection = KeycloakOpenIDConnection(
server_url="http://localhost:8080/",
username="admin",
password="admin",
realm_name="master",
client_id="admin-cli",
)

keycloak_admin = KeycloakAdmin(connection=keycloak_connection)

keycloak_admin.create_realm(
{
"realm": "argilla",
"enabled": True,
"displayName": "Argilla",
"userManagedAccessAllowed": True,
}
)
keycloak_connection = KeycloakOpenIDConnection(
server_url="http://localhost:8080/",
username="admin",
password="admin",
user_realm_name="master",
realm_name="argilla",
)

keycloak_admin = KeycloakAdmin(connection=keycloak_connection)

client = keycloak_admin.create_client(
{
"clientId": "example-client", # The client ID (you can choose a name)
"enabled": True,
"protocol": "openid-connect", # Protocol (you can use other protocols like 'saml' if needed)
"publicClient": False, # Set to False if the client will use client secrets
"directAccessGrantsEnabled": True,
"standardFlowEnabled": True,
"frontchannelLogout": True,
"secret": "client-secret", # Set a secret if it's not a public client
"redirectUris": [
"http://localhost:3000/*",
"http://localhost:6900/*",
], # Redirect URIs after authentication
}
)

keycloak_openid = KeycloakOpenID(server_url="http://localhost:8080/",
client_id="example-client",
realm_name="argilla")

public_key = keycloak_openid.public_key()

client_scope = keycloak_admin.create_client_scope({
"name": "example-client-scope_3",
"protocol": "openid-connect"
})

# Create Audience Mapper
mapper = keycloak_admin.add_mapper_to_client_scope(
client_scope_id=client_scope,
payload={
"name": "Client Audience",
"protocol": "openid-connect",
"protocolMapper": "oidc-audience-mapper",
"consentRequired": False,
"config": {
"included.client.audience": "example-client",
"id.token.claim": "false",
"access.token.claim": "true"
}
})

keycloak_admin.add_default_default_client_scope(client_scope)

new_user = keycloak_admin.create_user(
{
"email": "[email protected]",
"username": "example",
"enabled": True,
"firstName": "Example",
"lastName": "User",
"credentials": [
{
"value": "secret",
"type": "password",
}
],
}
)
```

## Set-up Argilla Server

After that you need to configure you endpoints in the `.oauth.yaml` same as this is done for the HuggingFace Oauth:

```yaml
# Change to `false` to disable HF oauth integration
#enabled: false

allow_http_redirect: true

providers:
- name: keycloak
client_id: <name of your client e.g. example-client>
client_secret: <value of your specified secret e.g. client-secret>
redirect_uri: http://localhost:3000/oauth/keycloak/callback # if you test locally
- name: huggingface
client_id: <create a new https://huggingface.co/settings/connected-applications>
client_secret: <create a new https://huggingface.co/settings/connected-applications>
redirect_uri: http://localhost:3000/oauth/huggingface/callback # if you test locally

# Allowed workspaces must exists
allowed_workspaces:
- name: default
```

Then you need to set the two environment variables:

```bash
export SOCIAL_AUTH_KEYCLOAK_AUTHORIZATION_URL="http://localhost:8080/realms/argilla/protocol/openid-connect/auth"
export SOCIAL_AUTH_KEYCLOAK_ACCESS_TOKEN_URL="http://localhost:8080/realms/argilla/protocol/openid-connect/token"
export SOCIAL_AUTH_KEYCLOAK_PUBLIC_KEY=MIIBIj...
export SOCIAL_AUTH_KEYCLOAK_KEY=argilla
```

- `http://localhost:8080` is your keycloak endpoint in this case the local docker
- `argilla` is the name of the realm configured above
- `MIIBIj...` is the public key from the script above `public_key = keycloak_openid.public_key()`