Skip to content

Commit

Permalink
Support client_credentials grant type
Browse files Browse the repository at this point in the history
  • Loading branch information
tomako committed Dec 17, 2024
1 parent a364d70 commit 1606b90
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 10 deletions.
31 changes: 26 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,17 +35,38 @@ MULTIPASS_IDENTITY_PROVIDERS = {
'title': 'Keycloak Identity Provider',
'identifier_field': 'email',
'keycloak_args': {
'client_name': '<client_name>',
'grant_type': 'client_credentials',
'client_id': '<client_id>',
'client_secret': '<client_secret>',
'username': <username>,
'password': <password>,
'access_token_url': <access-token-url>,
'realm_api_url': <realm-api-url>
'access_token_url': '<access-token-url>',
'realm_api_url': '<realm-api-url>'
}
}
}
```

The configuration values are following:

1. `grant_type`

Default value is `client_credentials`. In Keycloak, "Service accounts roles" must be enabled in client config (Client details/Settings/Capability).

`password` is also supported. In Keycloak, "Direct access grants" must be enabled in client config (Client details/Settings/Capability). In this case 2 additional fields must be added: `username` and `password`.

2. `client_id`

In Keycloak, Client details/Setting/Client ID field.
3. `client_secret`

In Keycloak, Client details/Credentials/Client Secret field.
4. `access_token_url`

In Keycloak, Realm settings/General/Endpoints/OpenID Endpoint Configuration/"token_endpoint".
5. `realm_api_url`

The URL format is `<base url>/admin/realms/<realm name>`, where the realm is where the users and user groups are configured.


### Performance

The library needs to get an API access token from Keycloak which typically takes 200-300ms. Set the `cache` key of the multipass identity provider configuration to the import path of a Flask-Caching instance or a function returning such an instance, or the instance itself to enable caching of tokens (until they expire) and group data (30 minutes).
Expand Down
14 changes: 9 additions & 5 deletions src/flask_multipass_keycloak.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,12 +209,16 @@ def _get_api_session(self):
if api_token:
api_session.headers.update({'Authorization': f'Bearer {api_token}'})
return api_session
basic = HTTPBasicAuth(self.keycloak_settings['client_name'], self.keycloak_settings['client_secret'])
data = {'username': self.keycloak_settings['username'],
'password': self.keycloak_settings['password'],
'grant_type': 'password'}
data = {'client_id': self.keycloak_settings['client_id'],
'client_secret': self.keycloak_settings['client_secret'],
'grant_type': self.keycloak_settings['grant_type']}
# Supported grant types: password and client_credentials
if data['grant_type'] == 'password':
data |= {'username': self.keycloak_settings['username'],
'password': self.keycloak_settings['password']}

self.logger.info('Requesting access token')
response = api_session.post(self.keycloak_settings['access_token_url'], auth=basic, data=data)
response = api_session.post(self.keycloak_settings['access_token_url'], data=data)
if response.status_code != 200:
error_message = self._get_error_message(response)
self.logger.error(f'{error_message} (URL: %s)', response.url)
Expand Down

0 comments on commit 1606b90

Please sign in to comment.