- CSIRO Ontoserver ♥ Keycloak
This project demonstrates how to integrate CSIRO's Ontoserver, a FHIR-based terminology server, with Red Hat's Keycloak, an OpenID Connect-compliant Identity and Access Management server. It was written against an older version of Ontoserver and Keycloak and is now archived, as time constraints preclude the authors from updating it to the latest versions. The concepts and general setup should still be valid, but the specifics may have changed.
⚠ This article aims give a comprehensive introduction into the required concepts and detailed instructions on how to configure the different components. Due to this, paragraphs with actionable instructions are highlighted with "⚠" emoji, like this one. ⚠
It is in part quite opinionated, and some opinions or statements may be wrong or insecure, due to the author being new to all of this as well ;) If you spot issues, please do get in touch via GitHub issues!
Ontoserver relies on SMART-on-FHIR Backend Services Authorization. As the authorization/authentication specification for SMART-on-FHIR is derived from the OpenID Connect specification, a "generic" authentication server that supports OAuth2 and OIDC, such as Keycloak, can be used to authorize requests to Ontoserver.
This projects uses Docker Compose to orchestrate four services working in tandem:
db
: A PostgreSQL database both for Ontoserver and Keycloak. It is not exposed on the public interface, but only accessible from the internal network.ontoserver
: The Ontoserver instance that is being secured by Keycloak. It has security enabled and requires authentication for all API calls using SMART-on-FHIR.keycloak
: The Keycloak authentication server and identification provider.nginx
: a reverse proxy that sits in front ofontoserver
andkeycloak
, which also handles TLS termination (very much recommended!)
Apart from docker
and docker-compose
installed on your machine, you will
need a license to use Ontoserver and need to be logged into Docker Hub with your
authorized account. Please
talk to the Ontoserver team at CSIRO if
you do not hold a license for Ontoserver.
You will also need a SSL certificate chain and key in PEM format to secure calls
to your containers. The provided nginx SSL configuration assumes a
ssl_certificate
key containing your server certificate and all required
intermediates, along with a ssl_certicate_key
containing your private key. It
was generated using
Mozilla's SSL Config
tool. For the provided SSL/TLS configuration, you will also need to either
generate or download pre-generated Diffie-Hellman Parameters. See the
nginx/ssl.conf
for details.
When building the images in this docker-compose
project, a number of
customizations are carried out. Most importantly, the Keycloak database and
associated user are created in the database.
In the keycloak container, this configuration assumes that two text files
username.secret
and password.secret
are present in /opt/secrets/
. You must
create these files in the keycloak
directory! They will be used to authorize
the Super-Admin of your Keycloak installation, so make sure that they a) are
not trivial to guess and b) remain secret!. They should NEVER be added to
Git, in case you fork this repository, and are excluded using the .gitignore
.
These files should only contain the username/password, and optionally a trailing
newline.
⚠ Here is a checklist for the initial start-up ⚠
- docker hub logged-in with an authorised account
- PKI certificate issued from trusted CA, private key placed at
nginx/certs/certificate.key
, public key with the full certification chain atnginx/certs/certificate-chain.pem
-
nginx/certs/dhparam
generated or downloaded - username and password for Keycloak created,
noted securely, added to
keycloak/username.secret
andkeycloak/password.secret
⚠ After completing the checklist, you can start the suite of containers for the first time: ⚠
docker-compose pull && \
docker-compose build && \
docker-compose up
This will take a while. When all containers are created and initialized, you
will be able to access these routes from your machine (substitute localhost
with the FQDN of your machine if required):
- Ontoserver on https://localhost/, with
- the conformance statement on https://localhost/fhir/metadata
- the Ontoserver FHIR, management API and syndication routes
- The Keycloak landing page on https://localhost/keycloak with
- the admin console on https://localhost/auth/admin
You will now be able to set up Keycloak to provide the authentication service required.
The following explanation is rather brief and high-level. A good starting point for understanding OAuth 2.0 is this guide by Aaron Parecki. Much information is also available from the linked RFCs and specifications.
OAuth 2.0 is the protocol that powers authorization across the internet. Whenever you see a button "Sign-in with Google/Apple/GitHub", you are looking at OAuth 2.0. It is designed to be user-centric and browser-friendly. It is specified in RFC 6749 and RFC 6750. OpenID Connect is a layer on top of OAuth which adds Identity (i.e. authentication) to the protocol.
The core of OAuth is naturally an authorization server. This server maps user identities to access rights and issues verifiable tokens in the JSON Web Token (JWT) format specified in RFC 7519.
While OAuth 2.0 is an authorization service, it does not allow for verifying the identity of the end user. This is what OpenID Connect addresses. More information is available at https://openid.net/connect/.
Because OAuth 2.0 and OpenID Connect are robust, secure, and widely-used protocols, the SMART-on-FHIR specification, used for integrating personal healthcare apps with each other. A great introduction is also available at https://smilecdr.com/docs/security/smart_on_fhir_introduction.html. Strictly speaking, the security system of Ontoserver seems to be not entirely compliant with the SMART-on-FHIR subspecification, SMART Backend Services: Authorization Guide. Still, many concepts apply.
The SMART-on-FHIR specifications calls for callers of backend services dynamically register with the authorization server and present a signed access token when requesting authorization codes. This is not supported by Ontoserver.
Regardless, the current security model of Ontoserver requires that requests to secure endpoints present a valid Bearer token in JWT format, issued and cryptographically signed by a trusted authorization server, to grant access.
Because OpenID Connect is a modern protocol, the tokens are obtained using HTTP GET and POST operations. The specification supports multiple flows that define how such a token can be obtained. The issued tokens will contain claims that are interpreted by the receiving server to grant or deny access to resources.
The primary means that clients should support is the Direct flow,
specified here.
This flow relies on an short-lived authorization code that is issued by the
authorization server upon a GET request to the authorization endpoint of the
authorization server. The request for the authorization code is validated by the
authorization server, and the end-user is authenticated. If allowed, the
authorization server will perform a 302 Found
redirection to the specified
callback URL, with a parameter for the authorization code. This authorization
code can then be exchanged for the authorization token using a POST request.
This is done so that the authorization tokens are transmitted only in the HTTP
body, not in the header or URL fragments. When exchanging codes for tokens, the
client presents a credential that authenticates the client to the authorization
server, along with the code. This flow is illustrated in the following image.
Because it is not possible to store a credential in some clients (such as modern Single-Page Applications that don't have a backend service), the flow as described above is not practical for such clients. Historically, the Implicit flow was used instead, but this flow is not recommended any more because it will leak tokens in URL fragments, which are visible in the browser history and can be extracted by malicious browser extensions. Hence, you should NOT use this flow.
Instead, use the standard flow with the PKCE extension, specified in RFC 7636. This extension, in combination with modern JavaScript APIs that allow redirection without reloading, allows the use of the much more secure standard flow, while making it much harder for MITM attacks to occur. PKCE relies on exchanging dynamic keys instead of a static client secret when requesting codes and tokens. More information is available in the RFC, the OAuth documentation or e.g. in Aaron Parecki's guide or Auth0's documentation.
Log-in into the Keycloak Administration console (at https://localhost/auth/admin
if executing this project on a machine with graphical capabilities). The
credentials will be the ones provided in the {username,password}.secret
files
you created above.
We will need to carry out the following steps:
- Create a new Realm in which our Ontoserver users reside
- Add a Client in the newly-created Realm
- Set-Up Client Scopes in the Realm
- Create Roles in the Realm and/or Client
- Set-Up mappers for the Client Scopes and Roles
- Optionally create groups
- Create users and assign privileges, and possibly federation
A Realm serves as a namespace for users, groups, clients, client scopes and roles. In a fresh Keycloak installation, only one realm, Master exists. This realm handles authentication to the management console. Generally, you want to separate user administration from resource access as much as possible. Thus, you should add users to the Master realm only if they need to perform management tasks in Keycloak itself.
⚠ The first step is thus to create a new Realm for securing access to Ontoserver. When logged-in, the current realm will be shown below the Keycloak logo in the top-right. When you hover over the "Master" text, a button "Add realm" will be shown. Click it, then enter a suitable name for the new realm, like "Ontoserver" or your project name if you will secure further applications that interact with Ontoserver. ⚠
You may want to configure these settings:
- in the General tab
- the Display name that is shown to users when logging in
- the frontend-url that is used when generating URLs that link back to
Keycloak, for example in the
.well-known
endpoint configuration. Set this tohttps://<your fqdn>/auth
to override the auto-detected value and check whether this is correct using the OpenID Endpoint Configuration button below.
- in the Login tab
- whether users can self-register, use the Forgot password functionality, etc.
- Whether SSL is required for requests
- in the Email tab
- server details for an SMTP server if you want users to register/reset passwords etc.
- token settings, like the login time-out
A client in OIDC is a software that users interact with. Users can be granted privileges within these services, but also control which data from their profile they want to share with the application. Whenever you see a "Login with {Google, GitHub, Facebook, Apple, etc.}" button, you are interacting with an OIDC client.
⚠ Within your realm, click on "Clients" in the left-hand pane and then "Create" in the top-right corner of the table. For the client id, you can chose any alphanumeric identifier. It is used in the URLs when requesting tokens. By default, it is also presented to the user if no friendly name is defined in the "Name" setting. For the Root URL, you will want to enter the FQDN of the system you are setting up, like https://ontoserver.your.domain.com. Choose Open ID Connect for the protocol! ⚠
⚠ You will NEED to configure the following settings: ⚠
- Access Type
- whether a secret is required when exchanging an authorization code for an authentication tokens (using the standard flow). This is recommended, as it greatly enhances security when you are able to use the standard flow. As outlined above, you will be able to use this flow if your client is able to "keep a secret" from the user. If your authorization flow happens server-side (Node, Java, ASP.NET etc.) this will likely be the case. Otherwise, you will need to either use the Implicit flow (not recommended!) or support the standard flow with PKCE enabled in your client!.
- Implicit Flow enabled
- If you plan on authorising applications that can't keep a secret, like JavaScript-based client-side applications, you may need the implicit flow enabled. This flow is not recommended due to security concerns!. You should instead use the Standard flow with Proof Key for Code Exchange.
- Direct Access Grants enabled
- if you have the credentials of the user available (i.e. you feature a log-in form directly in your application, or you reuse credentials across clients, BAD!), you can enable this setting to exchange this tuple for access tokens. This flow corresponds to the "Resource Owner Password Credentials" flow in the OAuth 2.0 specification. You MUST disable this unless specifically needed, since the OAuth 2.0 specification states that "the credentials should only be used when there is a high degree of trust between the resource owner and the client (e.g., the client is part of the device operating system or a highly privileged application), and when other authorization grant types are not available (such as an authorization code)". If you need to authorize scripts or other server-side applications, use the Service Accounts enabled setting instead
- Root URL
- see above, where the service that is being secured is available, e.g. https://ontoserver.your.domain.com
- Valid Redirect URIs
- Especially for Public clients, this is extremely important to configure.
When requesting tokens, this is the Allow-List for which URLs Keycloak will
redirect to. They should be
as specific as possible,
however, wildcards are allowed (only at the end, however). If your frontend
client is at https://ontoserver.your.domain.com/onto_client, you will enter
something like
/onto-client/oidc_redirect_uri
. You may also want to add callbacks (temporarily) for tools like Postman (https://oauth.pstmn.io/v1/callback) or OIDC Debugger (https://oidcdebugger.com/debug)
- Especially for Public clients, this is extremely important to configure.
When requesting tokens, this is the Allow-List for which URLs Keycloak will
redirect to. They should be
as specific as possible,
however, wildcards are allowed (only at the end, however). If your frontend
client is at https://ontoserver.your.domain.com/onto_client, you will enter
something like
- Base URL
- The (probably relative) URL Keycloak should use when redirecting to the
client,
/fhir/metadata
is a good choice here.
- The (probably relative) URL Keycloak should use when redirecting to the
client,
- Admin URL
- This setting is used when using a Keycloak-specific adapter. Leave it blank.
- Advanced Settings -> Proof Key for Code Exchange Code Challenge Method
- use the S256 challenge method for PKCE.
If you select confidential authorization, you will find the secret required in the "Credentials" tab.
Ontoserver authorizes requests to the FHIR endpoint (as of writing in September 2020 for version 6.0.x, this may change with the upcoming release of 6.1.x) based on the "scope" claim in the presented access token. Scopes can be shared across clients within a realm and have to be assigned to clients. This is used within SMART-on-FHIR, especially when authorizing user-facing applications, because these scopes can be set to require "Consent". The user will be asked to grant access to the apps when required, making them able to control access to their medical data. This is something where SMART-on-FHIR differs from the "vanilla" OIDC specification, which doesn't use scopes in this way. For Keycloak, they are mainly a convenient way to add reusable mappers to clients that map some attribute of the user principal to claims in the generated tokens.
For Ontoserver, and probably many other SMART-on-FHIR-compliant applications, we will need to make some adjustments to the client scopes already present.
⚠ First-up, we need to add the system/*.read
and system/*.write
scopes to
our realm. In the right-hand pane, click "Client Scopes", then "Create" in the
top-right. Add the two scopes, exacly as above, including the slash and
asterisk. If you want, you can also add descriptive texts shown to your users in
case you want to enable consent. The setting Include in Token Scope must be
enabled, and the protocol must be openid_connect. ⚠
Contrary to Ontoserver's
documentation, the
scopes onto/{api,synd}.{read,write}
are currently broken. This will likely be
fixed in the upcoming 6.1.x series, in which case this article will be updated
accordingly. Feel free to add the four scopes anyway. You can leave the Default
Client Scopes and the already-present scopes as-is. Some of these are mandated
by the OIDC specification and are used by some features of Keycloak within your
Realm (the self-management console available to users, for example!), so remove
them at your own risk.
⚠ Still, we need to remove some scopes from our Ontoserver client, as the
associated mappers will confuse Ontoserver. Also, we need to make the new scopes
available to the client in the first place. Head over to your client, and select
the "Client Scopes" tab. Remove all assigned default client scopes and all
assigned optional client scopes. Then add the system/*.{read,write}
and the
onto/{api,synd}.{read,write}
scopes (if added) to the default client scopes. ⚠
In this way, the scopes will get added into the scope
claim of every token
automatically. Optional client scopes will only get added when the
authentication requests includes the desired scopes. Right now, all scopes would
get added for every user. We will make sure that only users in the correct
groups/with the correct roles are allowed to use those scopes in the next steps.
If desired, you could also make some scopes optional if your application is
aware of these scopes and will request them when needed.
Since your use case will likely require different levels of authorization, we
will need to set-up some roles that users can assume. These roles will then be
linked to groups (which users belong to, and which can have roles assigned) and
scopes. They are also (currently, as of Ontoserver 6.0.4) required to get right
when securing the /api
and /synd
endpoints of Ontoserver.
Roles can be defined at the realm level (and thus used by multiple clients) or
at the client level. The author suggests that the roles for the FHIR endpoint
(which will be linked to system/*.{read,write}
) are created as realm roles,
while the Ontoserver-specific roles are created on the client level.
⚠ Start by adding roles for the FHIR endpoint by clicking on Roles in the left-hand pane, then Add Role. You should probably configure one role for reading and for writing for all three routes—if users always get access to these routes in tandem, use groups instead of assigning multiple scopes to your groups. For the FHIR scopes, the name doesn't technically matter, so using the name of the respective scope may be a good idea. After adding them, Keycloak will probably throw a 404 error when trying to display the role settings, and fail due to the "/*" in the name. Just go to the home page and select Roles again, the newly created role will be there. ⚠
Side note: you will always need to keep URL encoding the scopes for the FHIR endpoint in mind. Other than the 404 when creating the roles, Keycloak doesn't care about the "/*" as far as I can tell.
⚠ Next, add the client specific roles via Clients -> Ontoserver (or what
have you) -> Roles -> Add Role. You will need to use the following role names:
ROLE_API_READ, ROLE_API_WRITE, ROLE_SYND_READ, ROLE_SYND_WRITE
as they will be
used for authorization by Ontoserver! ⚠
Mappers determine which user, in which role and in which group, are granted which claims, and which claims are added into the generated tokens.
First-up, we want to make sure that only authorized users belonging to the right groups are able to claim scopes. This will change the behaviour of the Assigned Default Client Scopes you defined above: When you define a Scope mapping for a Client Scope (the terminology is a bit ambiguous here!), you restrict the assignment of the scope to users having that role. Whenever a user requests a token, Keycloak will look at their roles, and the default client scopes, and issue a token containing all of the default client scopes that the user is authorised to access, based on their role membership. Without those mappings, the default client scopes would be added to all tokens, regardless of role membership!
⚠ Go to Client Scopes, and select the system/*.read
scope. Then select
"Scope" in the tab bar and add the system/*.read
role to the assigned role.
Repeat this for the system/*.write
scope.⚠
⚠ If you added the ontoserver-specific clients scopes as well, you will need to select the respective roles by selecting your client, as the roles are (hopefully?) defined at the client level ⚠
Next, you will need to add a Mapper to the client. This is to support the
role-based access control (RBAC) that is required for authorizing calls to the
ontoserver-specific routes. Again, as of 6.0.x, the documentation is currently
incorrect. Using scopes of the form onto/{api,synd}.{read,write}
does not
work and passing the expected roles in the authorities
claim is required. The
following mapper will accomplish that based on the roles the current user has.
⚠ Go to your client and select Mappers. Click Create. Add an arbitrary name,
such as authorities from user client roles
. Make sure to select User Client
Role as the Mapper Type, and select your client id. Realm Role Prefix
should be empty, and Multivalued should be on. Enter authorities
as the
Token Claim Name and String
as the _Claim JSON type` (not JSON!). Leave the
three toggles on, so that the claim gets added to all tokens. ⚠
You will likely have multiple users that perform similar tasks, such as administrators, content creators, system users, or general users. To grant those users the right to access particular resources, you could directly assign them roles. This is error-prone, because many users assume multiple roles. A better way is to use Groups, which are a collection of roles, for each of the tasks a user should carry out. The exact configuration you will create will most likely look different to the one described below.
You can nest groups, which will inherit the role mappings of their parent. For example, every user that has write access to the syndication API should also have read access. You can map the read access in the top-level group and create a group as an child of that read-only group.
⚠ Configure some Groups that fit your requirements. Here is a rather technical example: ⚠
⚠ Don't forget to configure Role Mappings that map realm and/or client roles to the group: ⚠
In the example above, the {api,fhir,synd}
groups have the respective read
roles granted, while the nested groups additionally have the respective write
roles. Only ontoserver
has no group mapping.
⚠ You should also configure at least one default group in which new users are
placed. For the example above, the likely candidate is ontoserver/fhir
for
read-only access on a locked-down server. This setting is especially important
if you a) allow users to self-register or b) use a federation mechanism like
LDAP or an external identity provider like Google, GitHub and the like. ⚠
Next-up, you will need some users in your new installation (if you don't plan on setting up an external IDP or LDAP/Kerberos federation). Since we added a default group, every user will at least have some access to Ontoserver.
By default, Keycloak doesn't show any users on the Users page, even if there are some configured. This is by design! You can either search for users or click the View all users next to the search box (this will list all users in your LDAP if configured).
⚠ Create some users for your realm. The only required parameter when manually creating users is the username. If required, add some Required User Actions the user will have to perform when logging in the next time. You can also set a password yourself in the Credentials tab. If you enable Temporary, it needs to be changed when the user next logs-in! You will also need to configure access to some groups. ⚠
You can evaluate which roles a user has on the Role Mappings page. This will show all realm- and client-level roles (for one selected client):
This concludes the required steps for configuring Keycloak for use with Ontoserver. Next up, you may configure some further options for Keycloak, before setting up Ontoserver itself.
You may want to set-up federation of users with LDAP or Kerberos or the option to register with external identity providers like Google, GitHub, or any other OAuth2- or SAML-compatible solution. Refer to Keycloak's documentation on federation and identity brokering for further details on how to do this.
You may also need to configure further users in your Master realm that have access to the administration console, as documented here.
For especially sensitive applications, you can also require Two-Factor Authentication (2FA), password policies or WebAuthn hardware-based 2FA, see the docs for this.
The realm that was created during the writing of this guide was exported and
made available in this repository. You can
import this realm when clicking the "New realm" button. This will set-up a realm
Ontoserver
featuring the roles, client scopes, clients, groups and mappings
shown in the screen-shots. The realm was exported on 2020-09-18 and will be kept
up-to-date along with the guide.
After configuring the realm, we will need to make sure that Ontoserver is configured in the configuration we require and trusts the tokens produced by Keycloak.
Open the docker-compose.yml
file in your copy of this repository in your
favourite text editor.
You will need to change several settings in the environment
section of the
ontoserver
service.
⚠ First, set the conformance.fhir.base
to the public URL of your installation.
This path should be reachable/resolvable from the server itself! ⚠
⚠ Next, you will need to decide which routes should be available read-only
without authentication. This is determined by
ontoserver.security.readOnly.{api,fhir,synd}
. In the provided configuration,
all three routes are locked-down and only fhir/metadata
can be accessed
without authorization. ⚠
You can also adjust the conformance.security.description
to explain (to
humans) how the security of your installation works.
⚠ You will need to adjust the URL of the authorization and token services to
your installation, these are the conformance.security.{authorize,token}
settings. They will be of the form
https://<your FQDN>/auth/realms/<your realm name>/protocol/openid-connect/{authorize,token}
.
You can view the correct settings in the "OpenID Endpoint Configuration" JSON
document in the Realm Settings section. ⚠
⚠ One of the most important settings to get right is the
ontoserver.security.token.secret
configuration. This is used to verify the
signatures of the JSON Web Tokens presented to Ontoserver when making
authenticated calls. If it is not set correctly, the token will be rejected! To
configure this, go to the Realm Settings, select the Keys tab, and click the
Public Key button in the RS256 row. Copy the entire string to the clipboard
and paste it over the pre-defined key. Keep the markers intact! ⚠
The setting should look like this, with leading and trailing markers. Every marker has 5 leading and trailing dashes. You can include newlines before/after the markers. Whitespace is ignored (outside of the key itself, at least), so you can use auto-formatting features in your text editor safely without messing up the setting:
- ontoserver.security.token.secret=-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApeS3BVDSzwmrKZqcQoTR8bZoaTcyFovmgDsRYclvbnJ10Jw7gM6epUenDyXuW3x0EZjkvA12SsvcPp1mLnY1qaLMb/4gLAWUgbjUif9wcWzQHe4SqzWMKHZAalszGkB9x045kYdFfLdVMAh1UQsB9CZFUEeKtR4GD85bllZQAG/NsDlCjNH119RS+qQUwB2eQiVcVDgkVCovbzB8olbdFw11s8/I1r/ZGGvEhxthHfqvX1o7JbXfqHu7lgQu+FE9f820ySXBQwJOnDR4MOsGJl2eT8t2cH4aqUxH/qO/a9oMl/3eu0ezkUq+L5cgYRJ4frvDlVoIZ4284aJSAPwdpwIDAQAB
-----END PUBLIC KEY-----
Note that the docs state the following regarding the secret: When configuring Ontoserver to work with an authorization server, this parameter should be the shared key (using HS256 shared secret/symmetric key). Since version 5.5 of Ontoserver, an asymmetric (RS256 public-private) key is supported, although not recommended due to potential performance degradation. As far as I am aware, it is not possible to define a HS256 key for token signing, and in fact only really supports RSA-based (asymmetric) key signing, where a Red Hed employee states that HMAC-based signing would be a potential vulnerability if the shared symmetric key is leaked to an attacker. In such a scenario, the attacker could generate their own valid tokens, bypassing the Keycloak server entirely!
With everything in place, you can restart your ensemble of servers.
You can test authentication using Postman with this collection.
The Postman collection and environment is also provided in this repo.
If required, change the included environment to suit your needs:
You can use the fhir Metadata
request to view the metadata, which is possible
in all configurations. You should now request a token:
Weirdly, it is not possible to pass a nonce
(number only used once) for
implicit requests. For the OpenID Connect's implicit flow, this parameter is
required
as per the specification,
so that Keycloak rejects the request. Since
this flow is not recommended anyway
(yes, really don't use it anymore)
and the standard flow with PKCE enabled
should be used instead
to make sure that authorization tokens are not leaked in redirection URLs, this
should not matter too much.
A number of tools exist that make debugging authentication with OAuth/OIDC easier.
You can inspect the content of JSON Web Tokens on https://jwt.io. If you add the RS256 public key in the respective field (including the leading and trailing markers), it will also verify the signature for you.
Another fantastic tool is https://oidcdebugger.com. This tool can request authorization codes for you, and can also make requests using the implicit flow. You will need to (temporarily) add the redirect URL to the allowed redirect URLs of your client.
To check which mappers add claims to your tokens and which realm/client roles a certain user has, you can use the "Evaluate" tab under the "Client Scopes" tab of your client:
If you get the following error, the access token includes an audience (aud) claim that Ontoserver does not accept.
{
"error": "access_denied",
"error_description": "Invalid token does not contain resource id (oauth2-resource)"
}
If you take a look at the access token using a JSON Web Token inspection took, for example using this token, you will find a claim like this:
"aud": "account",
This is added when the roles
default client scope is added to the client you
are requesting tokens for. You can either remove the offending mapper in the
roles
client scope (first image) or remove the default client scope (second
image).
This claim is added to counteract impersonation across clients. As the
JWT specification states,
the client MUST tokens with reject unexpected audiences (if supplied, which is
optional!), on the assumption that the credential was issued for another client
and used maliciously. However, Ontoserver expects the audience oauth-resource
.
The easiest approach is thus to remove the offending claim. You could also
enforce audience with
hard-coded audience,
if desired.
If you get the following error when sending requests with a token to Ontoserver,
your RS256 token is not set correctly in docker-compose.yml
. See
the section Ontoserver Configuration
for details.
{
"error": "invalid_token",
"error_description": "Cannot convert access token to JSON"
}