Implemented Security Providers
Helidon provides the following security providers for endpoint protection:
| Provider | Type | Outbound supported | Description |
|---|---|---|---|
Authentication |
✅ |
Open ID Connect supporting JWT, Scopes, Groups and OIDC code flow |
|
Authentication |
✅ |
HTTP Basic Authentication support |
|
Authentication |
🚫 |
HTTP Digest Authentication support |
|
Authentication |
✅ |
Asserting a user based on a header value |
|
Authentication |
✅ |
Protecting service to service communication through signatures |
|
Role Mapping |
🚫 |
Retrieves roles from IDCS provider for authenticated user |
|
Authorization |
🚫 |
Attribute based access control authorization policies |
The following providers are no longer evolved:
| Provider | Type | Outbound supported | Description |
|---|---|---|---|
Authentication |
✅ |
Deprecated! Authenticates a token from request against Google servers |
|
Authentication |
✅ |
JWT tokens passed from frontend |
OIDC Provider
Open ID Connect security provider.
Setup
<dependency>
<groupId>io.helidon.microprofile</groupId>
<artifactId>helidon-microprofile-oidc</artifactId>
</dependency>
Open ID Connect security provider
oidc
This type provides the following service implementations:
-
io.helidon.security.spi.AuthenticationProvider -
io.helidon.security.spi.SecurityProvider
Configuration options
| key | type | default value | description |
|---|---|---|---|
|
boolean |
|
Whether to check if current IP address matches the one access token was issued for. This check helps with cookie replay attack prevention. |
|
string |
|
Audience of issued tokens. |
|
URI |
|
URI of an authorization endpoint used to redirect users to for logging-in. If not defined, it is obtained from oidcMetadata(Resource), if that is not defined an attempt is made to use identityUri(URI)/oauth2/v1/authorize. |
|
string |
|
Configure base scopes. By default, this is DEFAULT_BASE_SCOPES. If scope has a qualifier, it must be used here. |
|
boolean |
|
Configure audience claim check. |
|
|
Set the configuration related to the client credentials flow. |
|
|
string |
|
Client ID as generated by OIDC server. |
|
string |
|
Client secret as generated by OIDC server. Used to authenticate this application with the server when requesting JWT based on a code. |
|
Duration |
|
Timeout of calls using web client. |
|
string |
|
Domain the cookie is valid for. Not used by default. |
|
boolean |
|
Whether to encrypt token cookie created by this microservice.
Defaults to |
|
boolean |
|
Whether to encrypt id token cookie created by this microservice.
Defaults to |
|
string |
|
Name of the encryption configuration available through Security.encrypt(String, byte[]) and
Security.decrypt(String, String).
If configured and encryption is enabled for any cookie,
Security MUST be configured in global or current |
|
char[] |
|
Master password for encryption/decryption of cookies. This must be configured to the same value on each microservice using the cookie. |
|
boolean |
|
Whether to encrypt refresh token cookie created by this microservice.
Defaults to |
|
boolean |
|
Whether to encrypt state cookie created by this microservice.
Defaults to |
|
boolean |
|
Whether to encrypt tenant name cookie created by this microservice.
Defaults to |
|
boolean |
|
When using cookie, if set to true, the HttpOnly attribute will be configured. Defaults to OidcCookieHandler.Builder.DEFAULT_HTTP_ONLY. |
|
long |
|
When using cookie, used to set MaxAge attribute of the cookie, defining how long the cookie is valid. Not used by default. |
|
string |
|
Name of the cookie to use. Defaults to DEFAULT_COOKIE_NAME. |
|
string |
|
Name of the cookie to use for id token. Defaults to DEFAULT_COOKIE_NAME_2. This cookie is only used when logout is enabled, as otherwise it is not needed. Content of this cookie is encrypted. |
|
string |
|
The name of the cookie to use for the refresh token. Defaults to DEFAULT_REFRESH_COOKIE_NAME. |
|
string |
|
The name of the cookie to use for the state storage. Defaults to DEFAULT_STATE_COOKIE_NAME. |
|
string |
|
The name of the cookie to use for the tenant name. Defaults to DEFAULT_TENANT_COOKIE_NAME. |
|
string |
|
Path the cookie is valid for. Defaults to "/". |
|
SameSite (LAX, STRICT, NONE) |
|
When using cookie, used to set the SameSite cookie value. Can be "Strict" or "Lax". |
|
boolean |
|
When using cookie, if set to true, the Secure attribute will be configured. Defaults to false. |
|
boolean |
|
Whether to use cookie to store JWT between requests. Defaults to DEFAULT_COOKIE_USE. |
|
|
Assign cross-origin resource sharing settings. |
|
|
boolean |
|
Force HTTPS for redirects to identity provider.
Defaults to |
|
string |
|
Full URI of this application that is visible from user browser. Used to redirect request back from identity server after successful login. |
|
|
A TokenHandler to process header containing a JWT. Default is "Authorization" header with a prefix "bearer ". |
|
|
boolean |
|
Whether to expect JWT in a header field. |
|
boolean |
|
Whether id token signature check should be enabled. Signature check is enabled by default, and it is highly recommended to not change that. Change this setting only when you really know what you are doing, otherwise it could case security issues. |
|
URI |
|
URI of the identity server, base used to retrieve OIDC metadata. |
|
URI |
|
Endpoint to use to validate JWT. Either use this or set signJwk(JwkKeys) or signJwk(Resource). |
|
string |
|
Issuer of issued tokens. |
|
int |
|
Configure maximal number of redirects when redirecting to an OIDC provider within a single authentication attempt. Defaults to DEFAULT_MAX_REDIRECTS |
|
boolean |
|
If set to true, metadata will be loaded from default (well known) location, unless it is explicitly defined using oidc-metadata-resource. If set to false, it would not be loaded even if oidc-metadata-resource is not defined. In such a case all URIs must be explicitly defined (e.g. token-endpoint-uri). |
|
|
Resource configuration for OIDC Metadata containing endpoints to various identity services, as well as information about the identity server. |
|
|
boolean |
|
Whether authentication is required. By default, request will fail if the authentication cannot be verified. If set to true, request will process and this provider will abstain. |
|
boolean |
|
Allow audience claim to be optional. |
|
|
Add a new target configuration. |
|
|
PkceChallengeMethod (PLAIN, S256) |
|
Proof Key Code Exchange (PKCE) challenge creation method. Default value is PkceChallengeMethod.S256. Allowed values:
|
|
boolean |
|
Whether this provider should support PKCE.
Default value is |
|
boolean |
|
Whether to propagate identity. |
|
string |
|
Deprecated Proxy host to use. When defined, triggers usage of proxy for HTTP requests. Setting to empty String has the same meaning as setting to null - disables proxy. |
|
int |
|
Proxy port. Defaults to DEFAULT_PROXY_PORT |
|
string |
|
Deprecated Proxy protocol to use when proxy is used. Defaults to DEFAULT_PROXY_PROTOCOL. |
|
string |
|
Name of a query parameter that contains the JWT id token when parameter is used. |
|
string |
|
Name of a query parameter that contains the JWT access token when parameter is used. |
|
string |
|
Name of a query parameter that contains the tenant name when the parameter is used. Defaults to DEFAULT_TENANT_PARAM_NAME. |
|
boolean |
|
Whether to use a query parameter to send JWT token from application to this server. |
|
boolean |
|
By default, the client should redirect to the identity server for the user to log in. This behavior can be overridden by setting redirect to false. When token is not present in the request, the client will not redirect and just return appropriate error response code. |
|
string |
|
Configure the parameter used to store the number of attempts in redirect. Defaults to DEFAULT_ATTEMPT_PARAM |
|
string |
|
URI to register web server component on, used by the OIDC server to redirect authorization requests to after a user logs in or approves scopes. Note that usually the redirect URI configured here must be the same one as configured on OIDC server. Defaults to DEFAULT_REDIRECT_URI |
|
boolean |
|
Deprecated Can be set to |
|
string |
|
Audience of the scope required by this application. This is prefixed to the scope name when requesting scopes from the identity server. Defaults to empty string. |
|
string |
|
Configure one of the supported types of identity servers. If the type does not have an explicit mapping, a warning is logged and the default implementation is used. |
|
|
A resource pointing to JWK with public keys of signing certificates used to validate JWT. |
|
|
|
Configurations of the tenants |
|
|
ClientAuthentication (CLIENT_SECRET_BASIC, CLIENT_SECRET_POST, CLIENT_SECRET_JWT, PRIVATE_KEY_JWT, CLIENT_CERTIFICATE, NONE) |
|
Type of authentication to use when invoking the token endpoint. Current supported options:
Allowed values:
The JWT MUST contain the following REQUIRED Claim Values and MAY contain the following OPTIONAL Claim Values. Required:
Optional:
The JWT MUST contain the following REQUIRED Claim Values and MAY contain the following OPTIONAL Claim Values. Required:
Optional:
|
|
URI |
|
URI of a token endpoint used to obtain a JWT based on the authentication code. If not defined, it is obtained from oidcMetadata(Resource), if that is not defined an attempt is made to use identityUri(URI)/oauth2/v1/token. |
|
boolean |
|
Whether access token signature check should be enabled. Signature check is enabled by default, and it is highly recommended to not change that. Change this setting only when you really know what you are doing, otherwise it could case security issues. |
|
boolean |
|
Claim |
|
boolean |
|
Use JWK (a set of keys to validate signatures of JWT) to validate tokens. Use this method when you want to use default values for JWK or introspection endpoint URI. |
|
|
WebClient configuration used for outbound requests to the identity server. This configuration sets the values to the OIDC WebClient default configuration. |
Example code
See the example on GitHub.
security:
providers:
- oidc:
client-id: "client-id-of-this-service"
client-secret: "${CLEAR=changeit}"
identity-uri: "https://your-tenant.identity-server.com"
frontend-uri: "http://my-service:8080"
audience: "http://my-service"
cors:
allow-origins: ["https://foo.com", "https://there.com"]
allow-methods: ["PUT", "DELETE"]
outbound:
- name: "internal-services"
hosts: ["*.example.org"]
outbound-token:
header: "X-Internal-Auth"
How does it work?
At Helidon startup, if OIDC provider is configured, the following will happen:
-
client-id,client-secret, andidentityUriare validated - these must provide values -
Unless all resources are configured as local resources, the provider attempts to contact the
oidc-metadata.resourceendpoint to retrieve all endpoints
At runtime, depending on configuration…
If a request comes without a token or with insufficient scopes:
-
If
redirectis set totrue(default), request is redirected to the authorization endpoint of the identity server. If set to false,401is returned -
User authenticates against the identity server
-
The identity server redirects back to Helidon service with a code
-
Helidon service contacts the identity server’s token endpoint, to exchange the code for a JWT
-
The JWT is stored in a cookie (if cookie support is enabled, which it is by default)
-
Helidon service redirects to original endpoint (on itself)
Helidon obtains a token from request (from cookie, header, or query parameter):
-
Token is parsed as a singed JWT
-
We validate the JWT signature either against local JWK or against the identity server’s introspection endpoint depending on configuration
-
We validate the issuer and audience of the token if it matches the configured values
-
A subject is created from the JWT, including scopes from the token
-
We validate that we have sufficient scopes to proceed, and return
403if not -
Handling is returned to security to process other security providers
Multiple tenants
The OIDC provider also supports multiple tenants. To enable this feature, it is required to do several steps.
-
To enable the default multi-tenant support, add the
multi-tenant: trueoption to the OIDC provider configuration -
Specify the desired way to provide the tenant name. This step is done over adding the
tenant-id-styleconfiguration option. For more information, see the table below -
Add the tenants section to the OIDC provider configuration
tenants:
- name: "example-tenant"
# ... tenant configuration options
There are four ways to provide the required tenant information to Helidon by default.
| key | description | additional config options |
|---|---|---|
|
Tenant configuration will be selected based on your host present in the |
|
|
Similar to the Example: Host header value from inbound request is |
|
|
The tenant name information is expected to be provided through the configured custom header value. |
|
|
No tenant name finding is used. Default tenant name |
You can also implement a custom way of discovering the tenant name and tenant configuration. The custom tenant name discovery from request can be done by implementing SPI:
io.helidon.security.providers.oidc.common.spi.TenantIdProvider
and the custom tenant configuration discovery can be provided by implementing SPI:
io.helidon.security.providers.oidc.common.spi.TenantConfigProvider
Available tenant config options
Open ID Connect tenant configuration
Configuration options
| key | type | default value | description |
|---|---|---|---|
|
string |
|
Name of the tenant. |
| key | type | default value | description |
|---|---|---|---|
|
string |
|
Audience of issued tokens. |
|
URI |
|
URI of an authorization endpoint used to redirect users to for logging-in. If not defined, it is obtained from oidcMetadata(Resource), if that is not defined an attempt is made to use identityUri(URI)/oauth2/v1/authorize. |
|
string |
|
Configure base scopes. By default, this is DEFAULT_BASE_SCOPES. If scope has a qualifier, it must be used here. |
|
boolean |
|
Configure audience claim check. |
|
string |
|
Client ID as generated by OIDC server. |
|
string |
|
Client secret as generated by OIDC server. Used to authenticate this application with the server when requesting JWT based on a code. |
|
Duration |
|
Timeout of calls using web client. |
|
URI |
|
URI of the identity server, base used to retrieve OIDC metadata. |
|
URI |
|
Endpoint to use to validate JWT. Either use this or set signJwk(JwkKeys) or signJwk(Resource). |
|
string |
|
Issuer of issued tokens. |
|
boolean |
|
If set to true, metadata will be loaded from default (well known) location, unless it is explicitly defined using oidc-metadata-resource. If set to false, it would not be loaded even if oidc-metadata-resource is not defined. In such a case all URIs must be explicitly defined (e.g. token-endpoint-uri). |
|
|
Resource configuration for OIDC Metadata containing endpoints to various identity services, as well as information about the identity server. |
|
|
boolean |
|
Allow audience claim to be optional. |
|
string |
|
Audience of the scope required by this application. This is prefixed to the scope name when requesting scopes from the identity server. Defaults to empty string. |
|
string |
|
Configure one of the supported types of identity servers. If the type does not have an explicit mapping, a warning is logged and the default implementation is used. |
|
|
A resource pointing to JWK with public keys of signing certificates used to validate JWT. |
|
|
ClientAuthentication (CLIENT_SECRET_BASIC, CLIENT_SECRET_POST, CLIENT_SECRET_JWT, PRIVATE_KEY_JWT, CLIENT_CERTIFICATE, NONE) |
|
Type of authentication to use when invoking the token endpoint. Current supported options:
Allowed values:
The JWT MUST contain the following REQUIRED Claim Values and MAY contain the following OPTIONAL Claim Values. Required:
Optional:
The JWT MUST contain the following REQUIRED Claim Values and MAY contain the following OPTIONAL Claim Values. Required:
Optional:
|
|
URI |
|
URI of a token endpoint used to obtain a JWT based on the authentication code. If not defined, it is obtained from oidcMetadata(Resource), if that is not defined an attempt is made to use identityUri(URI)/oauth2/v1/token. |
|
boolean |
|
Use JWK (a set of keys to validate signatures of JWT) to validate tokens. Use this method when you want to use default values for JWK or introspection endpoint URI. |
How does that work?
Multi-tenant support requires to obtain tenant name from the incoming request. OIDC configuration is selected
based on the received tenant name. The way this tenant name has to be provided is configured via tenant-id-style
configuration. See How to enable tenants for more information. After matching tenant configuration
with the received name, the rest of the OIDC flow if exactly the same as in How does OIDC work.
Base OIDC configuration is treated as a default tenant, which is used, if no tenant name is provided. This default
tenant is having @default name specified.
It is also important to note, that each tenant configuration is based on the default tenant configuration (base OIDC configuration), and therefore its configuration do not need to change all the properties, if they do not differ from the base OIDC configuration.
CORS Settings
As an experimental feature, you can set up cross-origin handling for the redirect and logout endpoints in an optional cors block inside the oidc configuration.
The table below lists the configuration keys that identify the CORS characteristics.
| config key | type | default | description | CORS header name |
|---|---|---|---|---|
|
boolean |
|
Sets the allow credentials flag. |
|
|
string[] |
|
Sets the allowed headers. |
|
|
string[] |
|
Sets the allowed methods. |
|
|
string[] |
|
Sets the allowed origins. |
|
|
string[] |
|
Sets the expose headers. |
|
|
long |
|
Sets the maximum age. |
|
|
boolean |
|
Sets whether this config should be enabled or not. |
n/a |
If the cross-origin configuration is disabled (enabled = false), then the Helidon CORS implementation ignores the cross-origin configuration entry.
The following example of basic cross-origin
configuration
limits cross-origin resource sharing for PUT and
DELETE operations to only foo.com and there.com:
allow-origins: ["https://foo.com", "https://there.com"]
allow-methods: ["PUT", "DELETE"]
HTTP Basic Authentication Provider
HTTP Basic authentication support
Setup
<dependency>
<groupId>io.helidon.security.providers</groupId>
<artifactId>helidon-security-providers-http-auth</artifactId>
</dependency>
Overview
HTTP Basic Authentication provider
http-basic-auth
This type provides the following service implementations:
-
io.helidon.security.spi.SecurityProvider -
io.helidon.security.spi.AuthenticationProvider
Configuration options
| key | type | default value | description |
|---|---|---|---|
|
boolean |
|
Whether authentication is required. By default, request will fail if the authentication cannot be verified. If set to false, request will process and this provider will abstain. |
|
|
Add a new outbound target to configure identity propagation or explicit username/password. |
|
|
SubjectType (USER, SERVICE) |
|
Principal type this provider extracts (and also propagates). |
|
string |
|
Set the realm to use when challenging users. |
|
|
Set user store to validate users. Removes any other stores added through addUserStore(SecureUserStore). |
Example code
See the example on GitHub.
security:
providers:
- http-basic-auth:
realm: "helidon"
users:
- login: "john"
password: "${CLEAR=changeit}"
roles: ["admin"]
- login: "jack"
password: "changeit"
roles: ["user", "admin"]
outbound:
- name: "internal-services"
hosts: ["*.example.org"]
# Propagates current user's identity or identity from request property
outbound-token:
header: "X-Internal-Auth"
- name: "partner-service"
hosts: ["*.partner.org"]
# Uses this username and password
username: "partner-user-1"
password: "${CLEAR=changeit}"
How does it work?
Authentication of request
When a request is received without the Authorization: basic …. header, a challenge is returned to provide such
authentication.
When a request is received with the Authorization: basic …. header, the username and password is validated
against configured users (and users obtained from custom service if any provided).
Subject is created based on the username and roles provided by the user store.
Identity propagation
When identity propagation is configured, there are several options for identifying username and password to propagate:
-
We propagate the current username and password (inbound request must be authenticated using basic authentication).
-
We use username and password from an explicitly configured property (See
EndpointConfig.PROPERTY_OUTBOUND_IDandEndpointConfig.PROPERTY_OUTBOUND_SECRET) -
We use username and password associated with an outbound target (see example configuration above)
Identity is propagated only if:
-
There is an outbound target configured for the endpoint
-
Or there is an explicitly configured username/password for the current request (through request property)
Custom user store
Java service loader service io.helidon.security.providers.httpauth.spi.UserStoreService can be implemented to provide
users to the provider, such as when validated against an internal database or LDAP server.
The user store is defined so you never need the clear text password of the user.
Warning on security of HTTP Basic Authentication (or lack thereof)
Basic authentication uses base64 encoded username and password and passes it over the network. Base64 is only encoding, not encryption - so anybody that gets hold of the header value can learn the actual username and password of the user. This is a security risk and an attack vector that everybody should be aware of before using HTTP Basic Authentication. We recommend using this approach only for testing and demo purposes.
HTTP Digest Authentication Provider
HTTP Digest authentication support
Setup
<dependency>
<groupId>io.helidon.security.providers</groupId>
<artifactId>helidon-security-providers-http-auth</artifactId>
</dependency>
Overview
Http digest authentication security provider
http-digest-auth
This type provides the following service implementations:
-
io.helidon.security.spi.SecurityProvider -
io.helidon.security.spi.AuthenticationProvider
Configuration options
| key | type | default value | description |
|---|---|---|---|
|
Algorithm (MD5) |
|
Digest algorithm to use. Allowed values:
|
|
long |
|
How long will the nonce value be valid. When timed-out, browser will re-request username/password. |
|
boolean |
|
Whether authentication is required. By default, request will fail if the authentication cannot be verified. If set to false, request will process and this provider will abstain. |
|
SubjectType (USER, SERVICE) |
|
Principal type this provider extracts (and also propagates). |
|
Qop (NONE, AUTH) |
|
Only Allowed values:
|
|
string |
|
Set the realm to use when challenging users. |
|
string |
|
The nonce is encrypted using this secret - to make sure the nonce we get back was generated by us and to make sure we can safely time-out nonce values. This secret must be the same for all service instances (or all services that want to share the same authentication). Defaults to a random password - e.g. if deployed to multiple servers, the authentication WILL NOT WORK. You MUST provide your own password to work in a distributed environment with non-sticky load balancing. |
|
|
Set user store to obtain passwords and roles based on logins. |
Example code
security:
providers:
- http-digest-auth:
realm: "helidon"
server-secret: "${CLEAR=service-wide-secret-not-known-outside}"
users:
- login: "john"
password: "${CLEAR=changeit}"
roles: ["admin"]
- login: "jack"
password: "changeit"
roles: ["user", "admin"]
How does it work?
Authentication of request
When a request is received without the Authorization: digest …. header, a challenge is returned to provide such
authentication using WWW-Authenticate header.
When a request is received with the Authorization: digest …. header, the request is validated
against configured users (and users obtained from custom service if any provided).
Subject is created based on the username and roles provided by the user store.
Custom user store
Java service loader service io.helidon.security.providers.httpauth.spi.UserStoreService can be implemented to provide
users to the provider, such as when validated against an internal database or LDAP server.
The user store is defined so you never need the clear text password of the user.
Note on security of HTTP Digest Authentication
These authentication schemes should be obsolete, though they provide a very easy way to test a protected resource.
Header Authentication Provider
Asserts user or service identity based on a value of a header.
Setup
<dependency>
<groupId>io.helidon.security.providers</groupId>
<artifactId>helidon-security-providers-header</artifactId>
</dependency>
Overview
Security provider that extracts a username (or service name) from a header.
header-atn
This type provides the following service implementations:
-
io.helidon.security.spi.SecurityProvider -
io.helidon.security.spi.AuthenticationProvider
Configuration options
| key | type | default value | description |
|---|---|---|---|
|
|
Token handler to extract username from request. |
|
|
boolean |
|
Whether to authenticate requests. |
|
boolean |
|
Whether authentication is required. By default, request will fail if the username cannot be extracted. If set to false, request will process and this provider will abstain. |
|
|
Configure outbound target for identity propagation. |
|
|
|
Token handler to create outbound headers to propagate identity. If not defined, atnTokenHandler will be used. |
|
|
SubjectType (USER, SERVICE) |
|
Principal type this provider extracts (and also propagates). |
|
boolean |
|
Whether to propagate identity. |
Example code
security:
providers:
header-atn:
atn-token:
header: "X-AUTH-USER"
outbound:
- name: "internal-services"
hosts: ["*.example.org"]
# propagates the current user or service id using the same header as authentication
- name: "partner-service"
hosts: ["*.partner.org"]
# propagates an explicit username in a custom header
username: "service-27"
outbound-token:
header: "X-Service-Auth"
How does it work?
This provider inspects a specified request header and extracts the username/service name from it and asserts it as current subject’s principal.
This can be used when we use perimeter authentication (e.g. there is a gateway that takes care of authentication and propagates the user in a header).
Identity propagation
Identity is propagated only if an outbound target matches the target service.
The following options exist when propagating identity: 1. We propagate the current username using the configured header 2. We use username associated with an outbound target (see example configuration above)
Caution
When using this provider, you must be sure the header cannot be explicitly configured by a user or another service. All requests should go through a gateway that removes this header from inbound traffic, and only configures it for authenticated users/services. Another option is to use this with fully trusted parties (such as services within a single company, on a single protected network not accessible to any users), and of course for testing and demo purposes.
HTTP Signatures Provider
Support for HTTP Signatures.
Setup
<dependency>
<groupId>io.helidon.security.providers</groupId>
<artifactId>helidon-security-providers-http-sign</artifactId>
</dependency>
Overview
HTTP header signature provider.
http-signatures
This type provides the following service implementations:
-
io.helidon.security.spi.AuthenticationProvider
Configuration options
| key | type | default value | description |
|---|---|---|---|
|
boolean |
|
Enable support for Helidon versions before 3.0.0 (exclusive). Until version 3.0.0 (exclusive) there was a trailing end of line added to the signed
data.
To be able to communicate cross versions, we must configure this when talking to older versions of Helidon.
Default value is |
|
HttpSignHeader[] (SIGNATURE, AUTHORIZATION, CUSTOM) |
|
Add a header that is validated on inbound requests. Provider may support more than one header to validate. Allowed values:
|
|
|
Add inbound configuration. This is used to validate signature and authenticate the party. The same can be done through configuration: {
name = "http-signatures"
class = "HttpSignProvider"
http-signatures {
inbound {
# This configures the InboundClientDefinition
keys: [
{
key-id = "service1"
hmac.secret = "${CLEAR=password}"
}]
}
}
}
|
|
|
boolean |
|
Set whether the signature is optional. If set to true (default), this provider will SecurityResponse.SecurityStatus.ABSTAIN from this request if signature is not present. If set to false, this provider will SecurityResponse.SecurityStatus.FAILURE fail if signature is not present. |
|
|
Add outbound targets to this builder. The targets are used to chose what to do for outbound communication. The targets should have OutboundTargetDefinition attached through OutboundTarget.Builder.customObject(Class, Object) to tell us how to sign the request. The same can be done through configuration: {
name = "http-signatures"
class = "HttpSignProvider"
http-signatures {
targets: [
{
name = "service2"
hosts = ["localhost"]
paths = ["/service2/.*"]
# This configures the OutboundTargetDefinition
signature {
key-id = "service1"
hmac.secret = "${CLEAR=password}"
}
}]
}
}
|
|
|
string |
|
Realm to use for challenging inbound requests that do not have "Authorization" header in case header is HttpSignHeader.AUTHORIZATION and singatures are not optional. |
|
|
Override the default inbound required headers (e.g. headers that MUST be signed and headers that MUST be signed IF present). Defaults:
Note that this provider DOES NOT validate the "Digest" HTTP header, only the signature. |
Example code
See the example on GitHub.
security:
providers:
- http-signatures:
inbound:
keys:
- key-id: "service1-hmac"
principal-name: "Service1 - HMAC signature"
hmac.secret: "${CLEAR=changeit}"
- key-id: "service1-rsa"
principal-name: "Service1 - RSA signature"
public-key:
keystore:
resource.path: "src/main/resources/keystore.p12"
passphrase: "changeit"
cert.alias: "service_cert"
outbound:
- name: "service2-hmac"
hosts: ["localhost"]
paths: ["/service2"]
signature:
key-id: "service1-hmac"
hmac.secret: "${CLEAR=changeit}"
- name: "service2-rsa"
hosts: ["localhost"]
paths: ["/service2-rsa.*"]
signature:
key-id: "service1-rsa"
private-key:
keystore:
resource.path: "src/main/resources/keystore.p12"
passphrase: "changeit"
key.alias: "myPrivateKey"
Signature basics
-
standard: based on https://tools.ietf.org/html/draft-cavage-http-signatures-03
-
key-id: an arbitrary string used to locate signature configuration - when a request is received the provider locates validation configuration based on this id (e.g. HMAC shared secret or RSA public key). Commonly used meanings are: key fingerprint (RSA); API Key
How does it work?
Inbound Signatures We act as a server and another party is calling us with a signed HTTP request. We validate the signature and assume identity of the caller.
Outbound Signatures
We act as a client and we sign our outgoing requests.
If there is a matching outbound target specified in configuration,
its configuration will be applied for signing the outgoing request,
otherwise there is no signature added
IDCS Role Mapper
A role mapper to retrieve roles from Oracle IDCS.
Setup
<dependency>
<groupId>io.helidon.security.providers</groupId>
<artifactId>helidon-security-providers-idcs-mapper</artifactId>
</dependency>
Single-tenant IDCS Role Mapper
IDCS role mapping provider
idcs-role-mapper
This type provides the following service implementations:
-
io.helidon.security.spi.SecurityProvider -
io.helidon.security.spi.SubjectMappingProvider
Configuration options
| key | type | default value | description |
|---|---|---|---|
|
|
Use explicit io.helidon.security.providers.common.EvictableCache for role caching. |
|
|
string |
|
Configure subject type to use when requesting roles from IDCS. Can be either IDCS_SUBJECT_TYPE_USER or IDCS_SUBJECT_TYPE_CLIENT. Defaults to IDCS_SUBJECT_TYPE_USER. |
|
|
Use explicit io.helidon.security.providers.oidc.common.OidcConfig instance, e.g. when using it also for OIDC provider. |
|
|
SubjectType[] (USER, SERVICE) |
|
Add a supported subject type. If none added, io.helidon.security.SubjectType.USER is used. If any added, only the ones added will be used (e.g. if you want to use both io.helidon.security.SubjectType.USER and io.helidon.security.SubjectType.SERVICE, both need to be added. |
Multi-tenant IDCS Role Mapper
Multitenant IDCS role mapping provider
idcs-role-mapper
This type provides the following service implementations:
-
io.helidon.security.spi.SecurityProvider -
io.helidon.security.spi.SubjectMappingProvider
Configuration options
| key | type | default value | description |
|---|---|---|---|
|
|
Use explicit io.helidon.security.providers.common.EvictableCache for role caching. |
|
|
string |
|
Configure subject type to use when requesting roles from IDCS. Can be either IDCS_SUBJECT_TYPE_USER or IDCS_SUBJECT_TYPE_CLIENT. Defaults to IDCS_SUBJECT_TYPE_USER. |
|
|
Configure token handler for IDCS Application name. By default the header IdcsMtRoleMapperProvider.IDCS_APP_HEADER is used. |
|
|
|
Configure token handler for IDCS Tenant ID. By default the header IdcsMtRoleMapperProvider.IDCS_TENANT_HEADER is used. |
|
|
|
Use explicit io.helidon.security.providers.oidc.common.OidcConfig instance, e.g. when using it also for OIDC provider. |
|
|
SubjectType[] (USER, SERVICE) |
|
Add a supported subject type. If none added, io.helidon.security.SubjectType.USER is used. If any added, only the ones added will be used (e.g. if you want to use both io.helidon.security.SubjectType.USER and io.helidon.security.SubjectType.SERVICE, both need to be added. |
Example code
See the example on GitHub.
security:
providers:
- idcs-role-mapper:
multitenant: false
oidc-config:
client-id: "client-id"
client-secret: "changeit"
identity-uri: "IDCS identity server address"
How does it work?
The provider asks the IDCS server to provide list of roles for the currently
authenticated user.
The result is cached for a certain period of time (see cache-config above).
ABAC Provider
Attribute based access control authorization provider.
Setup
<dependency>
<groupId>io.helidon.security.providers</groupId>
<artifactId>helidon-security-providers-abac</artifactId>
</dependency>
Overview
Attribute Based Access Control provider
abac
This type provides the following service implementations:
-
io.helidon.security.spi.SecurityProvider -
io.helidon.security.spi.AuthorizationProvider
Configuration options
| key | type | default value | description |
|---|---|---|---|
|
boolean |
|
Whether to fail if NONE of the attributes is validated. |
|
boolean |
|
Whether to fail if any attribute is left unvalidated. |
Configuration options
The following table shows all configuration options of the provider and their default values
| key | default value | description |
|---|---|---|
|
|
"Unvalidated" means: an attribute is defined, but there is no validator available for it |
|
|
"None validated" means: there was not a single attribute that was validated |
How does it work?
ABAC uses available validators and validates them against attributes of the authenticated user.
Combinations of fail-on-unvalidated and fail-if-none-validated:
-
true&true: Will fail if any attribute is not validated and if any has failed validation -
false&true: Will fail if there is one or more attributes present and NONE of them is validated or if any has failed validation, Will NOT fail if there is at least one validated attribute and any number of not validated attributes (and NONE failed) -
false&false: Will fail if there is any attribute that failed validation, Will NOT fail if there are no failed validation or if there are NONE validated
Any attribute of the following objects can be used:
-
environment (such as time of request) - e.g. env.time.year
-
subject (user) - e.g. subject.principal.id
-
subject (service) - e.g. service.principal.id
-
object (must be explicitly invoked by developer in code, as object cannot be automatically added to security context) - e.g. object.owner
This provider checks that all defined ABAC validators are validated. If there is a definition for a validator that is not checked, the request is denied (depending on configuration as mentioned above).
ABAC provider also allows an object to be used in authorization process, such as when evaluating if an object’s owner is the current user. The following example uses the Expression language validator to demonstrate the point in a JAX-RS resource:
@Authenticated
@Path("/abac")
public class AbacResource {
@GET
@Authorized(explicit = true)
@PolicyStatement("${env.time.year >= 2017 && object.owner == subject.principal.id}")
public Response process(@Context SecurityContext context) {
// probably looked up from a database
SomeResource res = new SomeResource("user");
AuthorizationResponse atzResponse = context.authorize(res);
if (atzResponse.isPermitted()) {
//do the update
return Response.ok().entity("fine, sir").build();
} else {
return Response.status(Response.Status.FORBIDDEN)
.entity(atzResponse.description().orElse("Access not granted"))
.build();
}
}
}
The following validators are implemented:
Role Validator
Checks whether user/service is in either of the required role(s).
Configuration Key: role-validator
Annotations: @RolesAllowed, @RoleValidator.Roles
WebServersecurity:
web-server.paths:
- path: "/user/*"
roles-allowed: ["user"]
@RolesAllowed("user")
@RoleValidator.Roles(value = "service_role", subjectType = SubjectType.SERVICE)
@Authenticated
@Path("/abac")
public class AbacResource {
}
Interaction with JAX-RS sub-resource locators
When using sub-resource locators in JAX-RS, the roles allowed are collected from each "level" of execution: - Application class annotations - Resource class annotations + resource method annotations - Sub-resource class annotations + sub-resource method annotations - Sub-resource class annotations + sub-resource method annotations (for every sub-resource on the path)
The RolesAllowed or Roles annotation to be used is the last one in the path as defined above.
Example 1:
There is a RolesAllowed("admin") defined on a sub-resource locator resource class.
In this case the required role is admin.
Example 2:
There is a RolesAllowed("admin") defined on a sub-resource locator resource class and
a RolesAllowed("user") defined on the method of the sub-resource that provides the response.
In this case the required role is user.
Scope Validator
Checks whether user has all the required scopes.
Configuration Key: scope-validator
Annotations: @Scope
WebServersecurity:
web-server.paths:
- path: "/user/*"
abac.scopes:
["calendar_read", "calendar_edit"]
@Scope("calendar_read")
@Scope("calendar_edit")
@Authenticated
@Path("/abac")
public class AbacResource {
}
Expression Language Policy Validator
Policy executor using Java EE policy expression language (EL)
Configuration Key: policy-javax-el
Annotations: @PolicyStatement
Example of a policy statement: ${env.time.year >= 2017}
WebServersecurity:
web-server.paths:
- path: "/user/*"
policy:
statement: "hasScopes('calendar_read','calendar_edit') AND timeOfDayBetween('8:15', '17:30')"
@PolicyStatement("${env.time.year >= 2017}")
@Authenticated
@Path("/abac")
public class AbacResource {
}
JAX-RS over the configurationserver:
features:
security:
endpoints:
- path: "/somePath"
config:
abac.policy-validator.statement: "\\${env.time.year >= 2017}"
Google Login Provider
Authenticates a token from request against Google identity provider
This provider is deprecated and will be removed in a future version of Helidon. Please use our OpenID Connect security provider instead.
Setup
<dependency>
<groupId>io.helidon.security.providers</groupId>
<artifactId>helidon-security-providers-google-login</artifactId>
</dependency>
Overview
Google Authentication provider
google-login
This type provides the following service implementations:
-
io.helidon.security.spi.SecurityProvider -
io.helidon.security.spi.AuthenticationProvider
Configuration options
| key | type | default value | description |
|---|---|---|---|
|
string |
|
Google application client id, to validate that the token was generated by Google for us. |
|
boolean |
|
If set to true, this provider will return io.helidon.security.SecurityResponse.SecurityStatus.ABSTAIN instead of failing in case of invalid request. |
|
|
Outbound configuration - a set of outbound targets that will have the token propagated. |
|
|
string |
|
Set proxy host when talking to Google. |
|
int |
|
Set proxy port when talking to Google. |
|
string |
|
Set the authentication realm to build challenge, defaults to "helidon". |
|
|
Token provider to extract Google access token from request, defaults to "Authorization" header with a "bearer " prefix. |
Example code
See the example on GitHub.
security:
providers:
- provider:
client-id: "Google client id"
How does it work?
We expect to receive a token (with sufficient scopes) from the inbound request,
such as when using the Google login button on a page.
The page has access to the token in javascript and can send it to backend with
every request in a header field (Authorization with `bearer ` prefix is assumed by default).
Once we receive the token in Helidon, we parse it and:
-
Validate if it timed out locally
-
Return a cached response (see
EvictableCachewith default values) -
Otherwise verify using Google API -
GoogleIdTokenVerifier
We build a subject from the Google token with the following attributes filled (if in token):
-
userId
-
email
-
name
-
emailVerified
-
locale
-
family_name
-
given_name
-
picture (URL)
Outbound security
The token will be propagated to outbound calls if an outbound target exists
that matches the invoked endpoint (see outbound configuration above).
JWT Provider
JWT token authentication and outbound security provider.
Setup
<dependency>
<groupId>io.helidon.security.providers</groupId>
<artifactId>helidon-security-providers-jwt</artifactId>
</dependency>
Overview
JWT authentication provider
jwt
This type provides the following service implementations:
-
io.helidon.security.spi.SecurityProvider -
io.helidon.security.spi.AuthenticationProvider
Configuration options
| key | type | default value | description |
|---|---|---|---|
|
boolean |
|
Whether to allow impersonation by explicitly overriding username from outbound requests using io.helidon.security.EndpointConfig.PROPERTY_OUTBOUND_ID property. By default this is not allowed and identity can only be propagated. |
|
boolean |
|
Configure support for unsigned JWT.
If this is set to |
|
|
Token handler to extract username from request. |
|
|
|
JWK resource used to verify JWTs created by other parties. |
|
|
string |
|
Audience expected in inbound JWTs. |
|
boolean |
|
Configure whether to verify signatures. Signatures verification is enabled by default. You can configure the provider not to verify signatures. Make sure your service is properly secured on network level and only accessible from a secure endpoint that provides the JWTs when signature verification is disabled. If signature verification is disabled, this service will accept ANY JWT |
|
boolean |
|
Whether to authenticate requests. |
|
boolean |
|
Whether authentication is required. By default, request will fail if the username cannot be extracted. If set to false, request will process and this provider will abstain. |
|
SubjectType (USER, SERVICE) |
|
Principal type this provider extracts (and also propagates). |
|
boolean |
|
Whether to propagate identity. |
|
|
Configuration of outbound rules. |
|
|
|
JWK resource used to sign JWTs created by us. |
|
|
string |
|
Issuer used to create new JWTs. |
|
boolean |
|
Claim |
Example code
See the example on GitHub.
security:
providers:
- provider:
atn-token:
jwk.resource.resource-path: "verifying-jwk.json"
jwt-audience: "http://my.service"
sign-token:
jwk.resource.resource-path: "signing-jwk.json"
jwt-issuer: "http://my.server/identity"
outbound:
- name: "propagate-token"
hosts: ["*.internal.org"]
- name: "generate-token"
hosts: ["1.partner-service"]
jwk-kid: "partner-1"
jwt-kid: "helidon"
jwt-audience: "http://1.partner-service"
How does it work?
JSON Web Token (JWT) provider has support for authentication and outbound security.
Authentication is based on validating the token (signature, valid before etc.) and on asserting the subject of the JWT subject claim.
For outbound, we support either token propagation (e.g. the token from request is propagated further) or support for generating a brand new token based on configuration of this provider.