Implemented Security Providers

Helidon provides the following security providers for endpoint protection:

Provider Type Outbound supported Description

OIDC Provider

Authentication

Open ID Connect supporting JWT, Scopes, Groups and OIDC code flow

HTTP Basic Authentication

Authentication

HTTP Basic Authentication support

HTTP Digest Authentication

Authentication

🚫

HTTP Digest Authentication support

Header Assertion

Authentication

Asserting a user based on a header value

HTTP Signatures

Authentication

Protecting service to service communication through signatures

IDCS Roles

Role Mapping

🚫

Retrieves roles from IDCS provider for authenticated user

ABAC Authorization

Authorization

🚫

Attribute based access control authorization policies

The following providers are no longer evolved:

Provider Type Outbound supported Description

Google Login

Authentication

Deprecated! Authenticates a token from request against Google servers

JWT Provider

Authentication

JWT tokens passed from frontend

OIDC Provider

Open ID Connect security provider.

Setup

Maven dependency
<dependency>
    <groupId>io.helidon.microprofile</groupId>
    <artifactId>helidon-microprofile-oidc</artifactId>
</dependency>

Open ID Connect security provider

Config key
oidc

This type provides the following service implementations:

  • io.helidon.security.spi.AuthenticationProvider

  • io.helidon.security.spi.SecurityProvider

Configuration options

Table 1. Optional configuration options
key type default value description

access-token-ip-check

boolean

true

Whether to check if current IP address matches the one access token was issued for. This check helps with cookie replay attack prevention.

audience

string

 

Audience of issued tokens.

authorization-endpoint-uri

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.

base-scopes

string

openid

Configure base scopes. By default, this is DEFAULT_BASE_SCOPES. If scope has a qualifier, it must be used here.

check-audience

boolean

true

Configure audience claim check.

client-credentials-config

 

Set the configuration related to the client credentials flow.

client-id

string

 

Client ID as generated by OIDC server.

client-secret

string

 

Client secret as generated by OIDC server. Used to authenticate this application with the server when requesting JWT based on a code.

client-timeout-millis

Duration

30000

Timeout of calls using web client.

cookie-domain

string

 

Domain the cookie is valid for. Not used by default.

cookie-encryption-enabled

boolean

false

Whether to encrypt token cookie created by this microservice. Defaults to false.

cookie-encryption-id-enabled

boolean

true

Whether to encrypt id token cookie created by this microservice. Defaults to true.

cookie-encryption-name

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 io.helidon.common.context.Context (this is done automatically in Helidon MP).

cookie-encryption-password

char[]

 

Master password for encryption/decryption of cookies. This must be configured to the same value on each microservice using the cookie.

cookie-encryption-refresh-enabled

boolean

true

Whether to encrypt refresh token cookie created by this microservice. Defaults to true.

cookie-encryption-state-enabled

boolean

true

Whether to encrypt state cookie created by this microservice. Defaults to true.

cookie-encryption-tenant-enabled

boolean

true

Whether to encrypt tenant name cookie created by this microservice. Defaults to true.

cookie-http-only

boolean

true

When using cookie, if set to true, the HttpOnly attribute will be configured. Defaults to OidcCookieHandler.Builder.DEFAULT_HTTP_ONLY.

cookie-max-age-seconds

long

 

When using cookie, used to set MaxAge attribute of the cookie, defining how long the cookie is valid. Not used by default.

cookie-name

string

JSESSIONID

Name of the cookie to use. Defaults to DEFAULT_COOKIE_NAME.

cookie-name-id-token

string

JSESSIONID_2

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.

cookie-name-refresh-token

string

JSESSIONID_3

The name of the cookie to use for the refresh token. Defaults to DEFAULT_REFRESH_COOKIE_NAME.

cookie-name-state

string

JSESSIONID_3

The name of the cookie to use for the state storage. Defaults to DEFAULT_STATE_COOKIE_NAME.

cookie-name-tenant

string

HELIDON_TENANT

The name of the cookie to use for the tenant name. Defaults to DEFAULT_TENANT_COOKIE_NAME.

cookie-path

string

/

Path the cookie is valid for. Defaults to "/".

cookie-same-site

SameSite (LAX, STRICT, NONE)

LAX

When using cookie, used to set the SameSite cookie value. Can be "Strict" or "Lax".

cookie-secure

boolean

false

When using cookie, if set to true, the Secure attribute will be configured. Defaults to false.

cookie-use

boolean

true

Whether to use cookie to store JWT between requests. Defaults to DEFAULT_COOKIE_USE.

cors

 

Assign cross-origin resource sharing settings.

force-https-redirects

boolean

false

Force HTTPS for redirects to identity provider. Defaults to false.

frontend-uri

string

 

Full URI of this application that is visible from user browser. Used to redirect request back from identity server after successful login.

header-token

 

A TokenHandler to process header containing a JWT. Default is "Authorization" header with a prefix "bearer ".

header-use

boolean

true

Whether to expect JWT in a header field.

id-token-signature-validation

boolean

true

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.

identity-uri

URI

 

URI of the identity server, base used to retrieve OIDC metadata.

introspect-endpoint-uri

URI

 

Endpoint to use to validate JWT. Either use this or set signJwk(JwkKeys) or signJwk(Resource).

issuer

string

 

Issuer of issued tokens.

max-redirects

int

5

Configure maximal number of redirects when redirecting to an OIDC provider within a single authentication attempt.

Defaults to DEFAULT_MAX_REDIRECTS

oidc-metadata-well-known

boolean

true

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).

oidc-metadata.resource

 

Resource configuration for OIDC Metadata containing endpoints to various identity services, as well as information about the identity server.

optional

boolean

false

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.

optional-audience

boolean

false

Allow audience claim to be optional.

outbound

 

Add a new target configuration.

pkce-challenge-method

PkceChallengeMethod (PLAIN, S256)

S256

Proof Key Code Exchange (PKCE) challenge creation method. Default value is PkceChallengeMethod.S256.

Allowed values:

  • PLAIN: No hashing will be applied. Challenge string will be the same as verifier.

  • S256: SHA-256 algorithm is used to hash the verifier value.

pkce-enabled

boolean

false

Whether this provider should support PKCE. Default value is false.

propagate

boolean

false

Whether to propagate identity.

proxy-host

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.

proxy-port

int

80

Proxy port. Defaults to DEFAULT_PROXY_PORT

proxy-protocol

string

http

Deprecated Proxy protocol to use when proxy is used. Defaults to DEFAULT_PROXY_PROTOCOL.

query-id-token-param-name

string

id_token

Name of a query parameter that contains the JWT id token when parameter is used.

query-param-name

string

accessToken

Name of a query parameter that contains the JWT access token when parameter is used.

query-param-tenant-name

string

h_tenant

Name of a query parameter that contains the tenant name when the parameter is used. Defaults to DEFAULT_TENANT_PARAM_NAME.

query-param-use

boolean

false

Whether to use a query parameter to send JWT token from application to this server.

redirect

boolean

false

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.

redirect-attempt-param

string

h_ra

Configure the parameter used to store the number of attempts in redirect.

Defaults to DEFAULT_ATTEMPT_PARAM

redirect-uri

string

/oidc/redirect

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

relative-uris

boolean

false

Deprecated Can be set to true to force the use of relative URIs in all requests, regardless of the presence or absence of proxies or no-proxy lists. By default, requests that use the Proxy will have absolute URIs. Set this flag to true if the host is unable to accept absolute URIs. Defaults to DEFAULT_RELATIVE_URIS.

scope-audience

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.

server-type

string

@default

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.

sign-jwk.resource

 

A resource pointing to JWK with public keys of signing certificates used to validate JWT.

tenants

 

Configurations of the tenants

token-endpoint-auth

ClientAuthentication (CLIENT_SECRET_BASIC, CLIENT_SECRET_POST, CLIENT_SECRET_JWT, PRIVATE_KEY_JWT, CLIENT_CERTIFICATE, NONE)

CLIENT_SECRET_BASIC

Type of authentication to use when invoking the token endpoint. Current supported options:

  • io.helidon.security.providers.oidc.common.OidcConfig.ClientAuthentication.CLIENT_SECRET_BASIC

  • io.helidon.security.providers.oidc.common.OidcConfig.ClientAuthentication.CLIENT_SECRET_POST

  • io.helidon.security.providers.oidc.common.OidcConfig.ClientAuthentication.NONE

Allowed values:

  • CLIENT_SECRET_BASIC: Clients that have received a client_secret value from the Authorization Server authenticate with the Authorization Server in accordance with Section 2.3.1 of OAuth 2.0 [RFC6749] using the HTTP Basic authentication scheme. This is the default client authentication.

  • CLIENT_SECRET_POST: Clients that have received a client_secret value from the Authorization Server, authenticate with the Authorization Server in accordance with Section 2.3.1 of OAuth 2.0 [RFC6749] by including the Client Credentials in the request body.

  • CLIENT_SECRET_JWT: Clients that have received a client_secret value from the Authorization Server create a JWT using an HMAC SHA algorithm, such as HMAC SHA-256. The HMAC (Hash-based Message Authentication Code) is calculated using the octets of the UTF-8 representation of the client_secret as the shared key. The Client authenticates in accordance with JSON Web Token (JWT) Profile for OAuth 2.0 Client Authentication and Authorization Grants [OAuth.JWT] and Assertion Framework for OAuth 2.0 Client Authentication and Authorization Grants [OAuth.Assertions].

The JWT MUST contain the following REQUIRED Claim Values and MAY contain the following OPTIONAL Claim Values.

Required: iss, sub, aud, jti, exp

Optional: iat - PRIVATE_KEY_JWT: Clients that have registered a public key sign a JWT using that key. The Client authenticates in accordance with JSON Web Token (JWT) Profile for OAuth 2.0 Client Authentication and Authorization Grants [OAuth.JWT] and Assertion Framework for OAuth 2.0 Client Authentication and Authorization Grants [OAuth.Assertions].

The JWT MUST contain the following REQUIRED Claim Values and MAY contain the following OPTIONAL Claim Values.

Required: iss, sub, aud, jti, exp

Optional: iat - CLIENT_CERTIFICATE: Authentication is done via the client certificate used with MTLS. The Returned access token is bound to this client certificate. The Client needs to have MTLS enabled for the OIDC. - NONE: The Client does not authenticate itself at the Token Endpoint, either because it uses only the Implicit Flow (and so does not use the Token Endpoint) or because it is a Public Client with no Client Secret or other authentication mechanism.

token-endpoint-uri

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.

token-signature-validation

boolean

true

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.

use-jwt-groups

boolean

true

Claim groups from JWT will be used to automatically add groups to current subject (may be used with jakarta.annotation.security.RolesAllowed annotation).

validate-jwt-with-jwk

boolean

true

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

 

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.

Configuration example
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:

  1. client-id, client-secret, and identityUri are validated - these must provide values

  2. Unless all resources are configured as local resources, the provider attempts to contact the oidc-metadata.resource endpoint to retrieve all endpoints

At runtime, depending on configuration…​

If a request comes without a token or with insufficient scopes:

  1. If redirect is set to true (default), request is redirected to the authorization endpoint of the identity server. If set to false, 401 is returned

  2. User authenticates against the identity server

  3. The identity server redirects back to Helidon service with a code

  4. Helidon service contacts the identity server’s token endpoint, to exchange the code for a JWT

  5. The JWT is stored in a cookie (if cookie support is enabled, which it is by default)

  6. Helidon service redirects to original endpoint (on itself)

Helidon obtains a token from request (from cookie, header, or query parameter):

  1. Token is parsed as a singed JWT

  2. We validate the JWT signature either against local JWK or against the identity server’s introspection endpoint depending on configuration

  3. We validate the issuer and audience of the token if it matches the configured values

  4. A subject is created from the JWT, including scopes from the token

  5. We validate that we have sufficient scopes to proceed, and return 403 if not

  6. 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.

  1. To enable the default multi-tenant support, add the multi-tenant: true option to the OIDC provider configuration

  2. Specify the desired way to provide the tenant name. This step is done over adding the tenant-id-style configuration option. For more information, see the table below

  3. 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.

Table 2. Possible tenant-id-style configuration options
key description additional config options

host-header

Tenant configuration will be selected based on your host present in the Host header value.

 

domain

Similar to the host-header style, but now the tenant name is identified just as a part of the host name. By default, it selects the third domain level.

Example: Host header value from inbound request is my.helidon.com → domain level 3 is my, domain level 2 is helidon and domain level 1 is com.

tenant-id-domain-level: <domain level>

token-handler

The tenant name information is expected to be provided through the configured custom header value.

tenant-id-handler:
  header: "my-custom-header"

none

No tenant name finding is used. Default tenant name @default is used instead.

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
Table 3. Required configuration options
key type default value description

name

string

 

Name of the tenant.

Table 4. Optional configuration options
key type default value description

audience

string

 

Audience of issued tokens.

authorization-endpoint-uri

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.

base-scopes

string

openid

Configure base scopes. By default, this is DEFAULT_BASE_SCOPES. If scope has a qualifier, it must be used here.

check-audience

boolean

true

Configure audience claim check.

client-id

string

 

Client ID as generated by OIDC server.

client-secret

string

 

Client secret as generated by OIDC server. Used to authenticate this application with the server when requesting JWT based on a code.

client-timeout-millis

Duration

30000

Timeout of calls using web client.

identity-uri

URI

 

URI of the identity server, base used to retrieve OIDC metadata.

introspect-endpoint-uri

URI

 

Endpoint to use to validate JWT. Either use this or set signJwk(JwkKeys) or signJwk(Resource).

issuer

string

 

Issuer of issued tokens.

oidc-metadata-well-known

boolean

true

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).

oidc-metadata.resource

 

Resource configuration for OIDC Metadata containing endpoints to various identity services, as well as information about the identity server.

optional-audience

boolean

false

Allow audience claim to be optional.

scope-audience

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.

server-type

string

@default

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.

sign-jwk.resource

 

A resource pointing to JWK with public keys of signing certificates used to validate JWT.

token-endpoint-auth

ClientAuthentication (CLIENT_SECRET_BASIC, CLIENT_SECRET_POST, CLIENT_SECRET_JWT, PRIVATE_KEY_JWT, CLIENT_CERTIFICATE, NONE)

CLIENT_SECRET_BASIC

Type of authentication to use when invoking the token endpoint. Current supported options:

  • io.helidon.security.providers.oidc.common.OidcConfig.ClientAuthentication.CLIENT_SECRET_BASIC

  • io.helidon.security.providers.oidc.common.OidcConfig.ClientAuthentication.CLIENT_SECRET_POST

  • io.helidon.security.providers.oidc.common.OidcConfig.ClientAuthentication.NONE

Allowed values:

  • CLIENT_SECRET_BASIC: Clients that have received a client_secret value from the Authorization Server authenticate with the Authorization Server in accordance with Section 2.3.1 of OAuth 2.0 [RFC6749] using the HTTP Basic authentication scheme. This is the default client authentication.

  • CLIENT_SECRET_POST: Clients that have received a client_secret value from the Authorization Server, authenticate with the Authorization Server in accordance with Section 2.3.1 of OAuth 2.0 [RFC6749] by including the Client Credentials in the request body.

  • CLIENT_SECRET_JWT: Clients that have received a client_secret value from the Authorization Server create a JWT using an HMAC SHA algorithm, such as HMAC SHA-256. The HMAC (Hash-based Message Authentication Code) is calculated using the octets of the UTF-8 representation of the client_secret as the shared key. The Client authenticates in accordance with JSON Web Token (JWT) Profile for OAuth 2.0 Client Authentication and Authorization Grants [OAuth.JWT] and Assertion Framework for OAuth 2.0 Client Authentication and Authorization Grants [OAuth.Assertions].

The JWT MUST contain the following REQUIRED Claim Values and MAY contain the following OPTIONAL Claim Values.

Required: iss, sub, aud, jti, exp

Optional: iat - PRIVATE_KEY_JWT: Clients that have registered a public key sign a JWT using that key. The Client authenticates in accordance with JSON Web Token (JWT) Profile for OAuth 2.0 Client Authentication and Authorization Grants [OAuth.JWT] and Assertion Framework for OAuth 2.0 Client Authentication and Authorization Grants [OAuth.Assertions].

The JWT MUST contain the following REQUIRED Claim Values and MAY contain the following OPTIONAL Claim Values.

Required: iss, sub, aud, jti, exp

Optional: iat - CLIENT_CERTIFICATE: Authentication is done via the client certificate used with MTLS. The Returned access token is bound to this client certificate. The Client needs to have MTLS enabled for the OIDC. - NONE: The Client does not authenticate itself at the Token Endpoint, either because it uses only the Implicit Flow (and so does not use the Token Endpoint) or because it is a Public Client with no Client Secret or other authentication mechanism.

token-endpoint-uri

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.

validate-jwt-with-jwk

boolean

true

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

allow-credentials

boolean

false

Sets the allow credentials flag.

Access-Control-Allow-Credentials

allow-headers

string[]

*

Sets the allowed headers.

Access-Control-Allow-Headers

allow-methods

string[]

*

Sets the allowed methods.

Access-Control-Allow-Methods

allow-origins

string[]

*

Sets the allowed origins.

Access-Control-Allow-Origins

expose-headers

string[]

 

Sets the expose headers.

Access-Control-Expose-Headers

max-age-seconds

long

3600

Sets the maximum age.

Access-Control-Max-Age

enabled

boolean

true

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

Maven dependency
<dependency>
    <groupId>io.helidon.security.providers</groupId>
    <artifactId>helidon-security-providers-http-auth</artifactId>
</dependency>

Overview

HTTP Basic Authentication provider

Config key
http-basic-auth

This type provides the following service implementations:

  • io.helidon.security.spi.SecurityProvider

  • io.helidon.security.spi.AuthenticationProvider

Configuration options

Table 5. Optional configuration options
key type default value description

optional

boolean

false

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.

outbound

 

Add a new outbound target to configure identity propagation or explicit username/password.

principal-type

SubjectType (USER, SERVICE)

USER

Principal type this provider extracts (and also propagates).

realm

string

helidon

Set the realm to use when challenging users.

users

 

Set user store to validate users. Removes any other stores added through addUserStore(SecureUserStore).

Example code

See the example on GitHub.

Configuration example
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:

  1. We propagate the current username and password (inbound request must be authenticated using basic authentication).

  2. We use username and password from an explicitly configured property (See EndpointConfig.PROPERTY_OUTBOUND_ID and EndpointConfig.PROPERTY_OUTBOUND_SECRET)

  3. We use username and password associated with an outbound target (see example configuration above)

Identity is propagated only if:

  1. There is an outbound target configured for the endpoint

  2. 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

Maven dependency
<dependency>
    <groupId>io.helidon.security.providers</groupId>
    <artifactId>helidon-security-providers-http-auth</artifactId>
</dependency>

Overview

Http digest authentication security provider

Config key
http-digest-auth

This type provides the following service implementations:

  • io.helidon.security.spi.SecurityProvider

  • io.helidon.security.spi.AuthenticationProvider

Configuration options

Table 6. Optional configuration options
key type default value description

algorithm

Algorithm (MD5)

MD5

Digest algorithm to use.

Allowed values:

  • MD5: MD5 algorithm.

nonce-timeout-millis

long

86400000

How long will the nonce value be valid. When timed-out, browser will re-request username/password.

optional

boolean

false

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.

principal-type

SubjectType (USER, SERVICE)

USER

Principal type this provider extracts (and also propagates).

qop

Qop (NONE, AUTH)

NONE

Only AUTH supported. If left empty, uses the legacy approach (older RFC version). AUTH-INT is not supported.

Allowed values:

  • NONE: Legacy approach - used internally to parse headers. Do not use this option when building provider. If you want to support only legacy RFC, please use HttpDigestAuthProvider.Builder.noDigestQop(). Only AUTH is supported, as auth-int requires access to message body.

  • AUTH: QOP "auth" - stands for "authentication".

realm

string

Helidon

Set the realm to use when challenging users.

server-secret

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.

users

 

Set user store to obtain passwords and roles based on logins.

Example code

Configuration example
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

Maven dependency
<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.

Config key
header-atn

This type provides the following service implementations:

  • io.helidon.security.spi.SecurityProvider

  • io.helidon.security.spi.AuthenticationProvider

Configuration options

Table 7. Optional configuration options
key type default value description

atn-token

 

Token handler to extract username from request.

authenticate

boolean

true

Whether to authenticate requests.

optional

boolean

false

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.

outbound

 

Configure outbound target for identity propagation.

outbound-token

 

Token handler to create outbound headers to propagate identity. If not defined, atnTokenHandler will be used.

principal-type

SubjectType (USER, SERVICE)

USER

Principal type this provider extracts (and also propagates).

propagate

boolean

false

Whether to propagate identity.

Example code

Configuration example
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

Maven dependency
<dependency>
    <groupId>io.helidon.security.providers</groupId>
    <artifactId>helidon-security-providers-http-sign</artifactId>
</dependency>

Overview

HTTP header signature provider.

Config key
http-signatures

This type provides the following service implementations:

  • io.helidon.security.spi.AuthenticationProvider

Configuration options

Table 8. Optional configuration options
key type default value description

backward-compatible-eol

boolean

false

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 false. In Helidon 2.x, this switch exists as well and the default is true, to allow communication between versions as needed.

headers

HttpSignHeader[] (SIGNATURE, AUTHORIZATION, CUSTOM)

 

Add a header that is validated on inbound requests. Provider may support more than one header to validate.

Allowed values:

  • SIGNATURE: Creates (or validates) a "Signature" header.

  • AUTHORIZATION: Creates (or validates) an "Authorization" header, that contains "Signature" as the beginning of its content (the rest of the header is the same as for SIGNATURE.

  • CUSTOM: Custom provided using a io.helidon.security.util.TokenHandler.

inbound.keys

 

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}"
         }]
     }
 }
}

optional

boolean

true

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.

outbound

 

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}"
         }
     }]
 }
}

realm

string

helidon

Realm to use for challenging inbound requests that do not have "Authorization" header in case header is HttpSignHeader.AUTHORIZATION and singatures are not optional.

sign-headers

 

Override the default inbound required headers (e.g. headers that MUST be signed and headers that MUST be signed IF present).

Defaults:

  • get, head, delete methods: date, (request-target), host are mandatory; authorization if present (unless we are creating/validating the HttpSignHeader.AUTHORIZATION ourselves

  • put, post: same as above, with addition of: content-length, content-type and digest if present

  • for other methods: date, (request-target)

Note that this provider DOES NOT validate the "Digest" HTTP header, only the signature.

Example code

See the example on GitHub.

Configuration example
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

Maven dependency
<dependency>
    <groupId>io.helidon.security.providers</groupId>
    <artifactId>helidon-security-providers-idcs-mapper</artifactId>
</dependency>

Single-tenant IDCS Role Mapper

IDCS role mapping provider

Config key
idcs-role-mapper

This type provides the following service implementations:

  • io.helidon.security.spi.SecurityProvider

  • io.helidon.security.spi.SubjectMappingProvider

Configuration options

Table 9. Optional configuration options
key type default value description

cache-config

 

Use explicit io.helidon.security.providers.common.EvictableCache for role caching.

default-idcs-subject-type

string

user

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.

oidc-config

 

Use explicit io.helidon.security.providers.oidc.common.OidcConfig instance, e.g. when using it also for OIDC provider.

subject-types

SubjectType[] (USER, SERVICE)

USER

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

Config key
idcs-role-mapper

This type provides the following service implementations:

  • io.helidon.security.spi.SecurityProvider

  • io.helidon.security.spi.SubjectMappingProvider

Configuration options

Table 10. Optional configuration options
key type default value description

cache-config

 

Use explicit io.helidon.security.providers.common.EvictableCache for role caching.

default-idcs-subject-type

string

user

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.

idcs-app-name-handler

 

Configure token handler for IDCS Application name. By default the header IdcsMtRoleMapperProvider.IDCS_APP_HEADER is used.

idcs-tenant-handler

 

Configure token handler for IDCS Tenant ID. By default the header IdcsMtRoleMapperProvider.IDCS_TENANT_HEADER is used.

oidc-config

 

Use explicit io.helidon.security.providers.oidc.common.OidcConfig instance, e.g. when using it also for OIDC provider.

subject-types

SubjectType[] (USER, SERVICE)

USER

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.

Configuration example
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

Maven dependency
<dependency>
    <groupId>io.helidon.security.providers</groupId>
    <artifactId>helidon-security-providers-abac</artifactId>
</dependency>

Overview

Attribute Based Access Control provider

Config key
abac

This type provides the following service implementations:

  • io.helidon.security.spi.SecurityProvider

  • io.helidon.security.spi.AuthorizationProvider

Configuration options

Table 11. Optional configuration options
key type default value description

fail-if-none-validated

boolean

true

Whether to fail if NONE of the attributes is validated.

fail-on-unvalidated

boolean

true

Whether to fail if any attribute is left unvalidated.

Example code

See the example on GitHub.

Configuration example
security:
  providers:
    - abac:

Configuration options

The following table shows all configuration options of the provider and their default values

key default value description

fail-on-unvalidated

true

"Unvalidated" means: an attribute is defined, but there is no validator available for it

fail-if-none-validated

true

"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:

  1. true & true: Will fail if any attribute is not validated and if any has failed validation

  2. 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)

  3. 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:

Example of using an object
@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

Configuration example for WebServer
security:
  web-server.paths:
    - path: "/user/*"
      roles-allowed: ["user"]
JAX-RS example
@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

Configuration example for WebServer
security:
  web-server.paths:
    - path: "/user/*"
      abac.scopes:
        ["calendar_read", "calendar_edit"]
JAX-RS example
@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}

Configuration example for WebServer
security:
  web-server.paths:
    - path: "/user/*"
      policy:
        statement: "hasScopes('calendar_read','calendar_edit') AND timeOfDayBetween('8:15', '17:30')"
JAX-RS example
@PolicyStatement("${env.time.year >= 2017}")
@Authenticated
@Path("/abac")
public class AbacResource {
}
Configuration example for JAX-RS over the configuration
server:
  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

Maven dependency
<dependency>
    <groupId>io.helidon.security.providers</groupId>
    <artifactId>helidon-security-providers-google-login</artifactId>
</dependency>

Overview

Google Authentication provider

Config key
google-login

This type provides the following service implementations:

  • io.helidon.security.spi.SecurityProvider

  • io.helidon.security.spi.AuthenticationProvider

Configuration options

Table 12. Optional configuration options
key type default value description

client-id

string

 

Google application client id, to validate that the token was generated by Google for us.

optional

boolean

false

If set to true, this provider will return io.helidon.security.SecurityResponse.SecurityStatus.ABSTAIN instead of failing in case of invalid request.

outbound

 

Outbound configuration - a set of outbound targets that will have the token propagated.

proxy-host

string

 

Set proxy host when talking to Google.

proxy-port

int

80

Set proxy port when talking to Google.

realm

string

helidon

Set the authentication realm to build challenge, defaults to "helidon".

token

`Authorization` header with `bearer` prefix

Token provider to extract Google access token from request, defaults to "Authorization" header with a "bearer " prefix.

Example code

See the example on GitHub.

Configuration example
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:

  1. Validate if it timed out locally

  2. Return a cached response (see EvictableCache with default values)

  3. 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

Maven dependency
<dependency>
    <groupId>io.helidon.security.providers</groupId>
    <artifactId>helidon-security-providers-jwt</artifactId>
</dependency>

Overview

JWT authentication provider

Config key
jwt

This type provides the following service implementations:

  • io.helidon.security.spi.SecurityProvider

  • io.helidon.security.spi.AuthenticationProvider

Configuration options

Table 13. Optional configuration options
key type default value description

allow-impersonation

boolean

false

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.

allow-unsigned

boolean

false

Configure support for unsigned JWT. If this is set to true any JWT that has algorithm set to none and no kid defined will be accepted. Note that this has serious security impact - if JWT can be sent from a third party, this allows the third party to send ANY JWT and it would be accpted as valid.

atn-token.handler

 

Token handler to extract username from request.

atn-token.jwk.resource

 

JWK resource used to verify JWTs created by other parties.

atn-token.jwt-audience

string

 

Audience expected in inbound JWTs.

atn-token.verify-signature

boolean

true

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

authenticate

boolean

true

Whether to authenticate requests.

optional

boolean

false

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.

principal-type

SubjectType (USER, SERVICE)

USER

Principal type this provider extracts (and also propagates).

propagate

boolean

true

Whether to propagate identity.

sign-token

 

Configuration of outbound rules.

sign-token.jwk.resource

 

JWK resource used to sign JWTs created by us.

sign-token.jwt-issuer

string

 

Issuer used to create new JWTs.

use-jwt-groups

boolean

true

Claim groups from JWT will be used to automatically add groups to current subject (may be used with jakarta.annotation.security.RolesAllowed annotation).

Example code

See the example on GitHub.

Configuration example
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.