mirror of
https://github.com/jlengrand/helidon.git
synced 2026-03-10 08:21:17 +00:00
Disable automatic propagation from security providers (#2357)
* Security providers no long automatically propagate. * Updated security provider documentation Signed-off-by: Tomas Langer <tomas.langer@oracle.com>
This commit is contained in:
234
docs/shared/security/providers/abac.adoc
Normal file
234
docs/shared/security/providers/abac.adoc
Normal file
@@ -0,0 +1,234 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Copyright (c) 2020 Oracle and/or its affiliates.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
=== ABAC Provider
|
||||
:description: Helidon Security ABAC Provider
|
||||
:keywords: helidon, security, authorization, abac
|
||||
|
||||
Attribute based access control authorization provider.
|
||||
|
||||
==== Setup
|
||||
|
||||
[source,xml]
|
||||
.Maven dependency
|
||||
----
|
||||
<dependency>
|
||||
<groupId>io.helidon.security.providers</groupId>
|
||||
<artifactId>helidon-security-providers-abac</artifactId>
|
||||
</dependency>
|
||||
----
|
||||
|
||||
[source,text]
|
||||
.Provider class name
|
||||
----
|
||||
io.helidon.security.providers.abac.AbacProvider
|
||||
----
|
||||
|
||||
[source,text]
|
||||
.Provider configuration key
|
||||
----
|
||||
abac
|
||||
----
|
||||
|
||||
==== Example code
|
||||
https://github.com/oracle/helidon/tree/master/examples/security/attribute-based-access-control[]
|
||||
|
||||
[source,yaml]
|
||||
.Configuration example
|
||||
----
|
||||
security:
|
||||
providers:
|
||||
- abac:
|
||||
----
|
||||
|
||||
==== Configuration options
|
||||
The following table shows all configuration options of the provider and their default values
|
||||
|
||||
[cols="2,2,5"]
|
||||
|
||||
|===
|
||||
|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:
|
||||
|
||||
[source,java]
|
||||
.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.getDescription().orElse("Access not granted"))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
|
||||
*The following validators are implemented:*
|
||||
|
||||
* <<Role Validator,Roles>>
|
||||
* <<Scope Validator,Scopes>>
|
||||
* <<Expression Language Policy Validator,EL Policy>>
|
||||
|
||||
==== Role Validator
|
||||
Checks whether user/service is in either of the required role(s).
|
||||
|
||||
Configuration Key: `role-validator`
|
||||
|
||||
Annotations: `@RolesAllowed`, `@RoleValidator.Roles`
|
||||
|
||||
[source,yaml]
|
||||
.Configuration example for `WebServer`
|
||||
----
|
||||
security:
|
||||
web-server.paths:
|
||||
- path: "/user[/{*}]"
|
||||
roles-allowed: ["user"]
|
||||
----
|
||||
|
||||
[source,java]
|
||||
.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`
|
||||
|
||||
[source,yaml]
|
||||
.Configuration example for `WebServer`
|
||||
----
|
||||
security:
|
||||
web-server.paths:
|
||||
- path: "/user[/{*}]"
|
||||
abac.scopes:
|
||||
["calendar_read", "calendar_edit"]
|
||||
----
|
||||
|
||||
[source,java]
|
||||
.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}`
|
||||
|
||||
[source,yaml]
|
||||
.Configuration example for `WebServer`
|
||||
----
|
||||
security:
|
||||
web-server.paths:
|
||||
- path: "/user[/{*}]"
|
||||
policy:
|
||||
statement: "hasScopes('calendar_read','calendar_edit') AND timeOfDayBetween('8:15', '17:30')"
|
||||
----
|
||||
|
||||
[source,java]
|
||||
.JAX-RS example
|
||||
----
|
||||
@PolicyStatement("${env.time.year >= 2017}")
|
||||
@Authenticated
|
||||
@Path("/abac")
|
||||
public class AbacResource {
|
||||
}
|
||||
----
|
||||
111
docs/shared/security/providers/google-login.adoc
Normal file
111
docs/shared/security/providers/google-login.adoc
Normal file
@@ -0,0 +1,111 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Copyright (c) 2020 Oracle and/or its affiliates.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
=== Google Login Provider
|
||||
:description: Helidon Security Google Login Provider
|
||||
:keywords: helidon, security, google
|
||||
|
||||
Authenticates a token from request against Google identity provider
|
||||
|
||||
==== Setup
|
||||
|
||||
[source,xml]
|
||||
.Maven dependency
|
||||
----
|
||||
<dependency>
|
||||
<groupId>io.helidon.security.providers</groupId>
|
||||
<artifactId>helidon-security-providers-google-login</artifactId>
|
||||
</dependency>
|
||||
----
|
||||
|
||||
[source,text]
|
||||
.Provider class name
|
||||
----
|
||||
io.helidon.security.providers.google.login.GoogleTokenProvider
|
||||
----
|
||||
|
||||
[source,text]
|
||||
.Provider configuration key
|
||||
----
|
||||
google-login
|
||||
----
|
||||
|
||||
==== Example code
|
||||
https://github.com/oracle/helidon/tree/master/examples/security/google-login[]
|
||||
|
||||
[source,yaml]
|
||||
.Configuration example
|
||||
----
|
||||
security:
|
||||
providers:
|
||||
- provider:
|
||||
client-id: "Google client id"
|
||||
----
|
||||
|
||||
==== Configuration options
|
||||
The following table shows all configuration options of the provider and their default values
|
||||
|
||||
[cols="2,2,5"]
|
||||
|
||||
|===
|
||||
|key |default value |description
|
||||
|
||||
|`client-id` |{nbsp} |Client id of an application. To create an application, use
|
||||
the Google developer console (https://developers.google.com/identity/sign-in/web/sign-in)
|
||||
|`optional` |`false` |If set to `true`, failure to authenticate will return `ABSTAIN` result instead of `FAILURE`. This is
|
||||
an important distinction when more than one provider is used
|
||||
|`realm` |`helidon` |Realm used in the challenge when authentication is not provided and it is required
|
||||
|`proxy-host` |none |Configuration of a proxy host to use when authenticating the user
|
||||
|`proxy-port` |`80` |Proxy port
|
||||
|`token` |`Authorization` header with `bearer` prefix |Configuration of the location of the token (see `TokenHandler`)
|
||||
|`outbound` |{nbsp} |A list of outbound configurations
|
||||
|`outbound.*.name` |{nbsp} |Required name of outbound configuration
|
||||
|`outbound.*.username` |{nbsp} |Optional username used for outbound security; if not provided, current identity is propagated
|
||||
|`outbound.*.password` |{nbsp} |Optional password used for outbound security
|
||||
|`outbound.*.transports` |any transport |An array of transports this outbound configuration should be used for
|
||||
|`outbound.*.hosts` |any host |An array of hosts this outbound configuration should be used for, can be a regular expression
|
||||
|`outbound.*.paths` |any path |An array of paths this outbound configuration should be used for (such as `/greet`), can be a regular expression
|
||||
|`outbound.*.methods` |any method |An array of HTTP methods this outbound configuration should be used for
|
||||
|===
|
||||
|
||||
==== 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).
|
||||
122
docs/shared/security/providers/header-assertion.adoc
Normal file
122
docs/shared/security/providers/header-assertion.adoc
Normal file
@@ -0,0 +1,122 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Copyright (c) 2018, 2020 Oracle and/or its affiliates.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
=== Header Authentication Provider
|
||||
:description: Helidon Security Header Provider
|
||||
:keywords: helidon, security, header
|
||||
|
||||
Asserts user or service identity based on a value of a header.
|
||||
|
||||
==== Setup
|
||||
|
||||
[source,xml]
|
||||
.Maven dependency
|
||||
----
|
||||
<dependency>
|
||||
<groupId>io.helidon.security.providers</groupId>
|
||||
<artifactId>helidon-security-providers-header</artifactId>
|
||||
</dependency>
|
||||
----
|
||||
|
||||
[source,text]
|
||||
.Provider class name
|
||||
----
|
||||
io.helidon.security.providers.header.HeaderAtnProvider
|
||||
----
|
||||
|
||||
[source,text]
|
||||
.Provider configuration key
|
||||
----
|
||||
header-atn
|
||||
----
|
||||
|
||||
==== Example code
|
||||
|
||||
[source,yaml]
|
||||
.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"
|
||||
----
|
||||
|
||||
==== Configuration options
|
||||
The following table shows all configuration options of the provider and their default values
|
||||
|
||||
[cols="2,2,5"]
|
||||
|
||||
|===
|
||||
|key |default value |description
|
||||
|
||||
|`optional` |`false` |If set to `true`, failure to authenticate will return `ABSTAIN` result instead of `FAILURE`. This is
|
||||
an important distinction when more than one provider is used
|
||||
|`authenticate` |`true` |If set to `false`, authentication will not be attempted (outbound security can still be used)
|
||||
|`propagate` |`false` |If explicitly set to `false`, identity propagation will not be done. Otherwise it is done if an `outbound`
|
||||
section is configured
|
||||
|`principal-type` |`USER` |Can be `USER` or `SERVICE`
|
||||
|`atn-token` |`none` | Token extraction and propagation, you can define which header to use and how to extract it
|
||||
|`outbound` |{nbsp} |A list of outbound configurations
|
||||
|`outbound.*.name` |{nbsp} |Required name of outbound configuration
|
||||
|`outbound.*.username` |{nbsp} |Optional username used for outbound security; if not provided, current identity is propagated
|
||||
|`outbound.*.transports` |any transport |An array of transports this outbound configuration should be used for
|
||||
|`outbound.*.hosts` |any host |An array of hosts this outbound configuration should be used for, can be a regular expression
|
||||
|`outbound.*.paths` |any path |An array of paths this outbound configuration should be used for (such as `/greet`), can be a regular expression
|
||||
|`outbound.*.methods` |any method |An array of HTTP methods this outbound configuration should be used for
|
||||
|`outbound.*.outbound-token` |same as `atn-token` |Configuration of outbound header used to propagate
|
||||
|`outbound.*.outbound-token.header` |{nbsp} |Name of the header used to propagate the token
|
||||
|`outbound.*.outbound-token.prefix` |{nbsp} |Prefix for the header value, such as `"username "` (only one of `prefix`, `regexp` and `format` should be defined, `regexp` wins over `prefix`, `format` wins over `regexp`)
|
||||
|`outbound.*.outbound-token.format` |{nbsp} |String format with a single parameter to create the header value, such as `"username %1s"`
|
||||
|`outbound.*.outbound-token.regexp` |{nbsp} |Regular expression to create the header value, such as `"username (.*)"`
|
||||
|===
|
||||
|
||||
==== 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.
|
||||
|
||||
144
docs/shared/security/providers/http-basic-auth.adoc
Normal file
144
docs/shared/security/providers/http-basic-auth.adoc
Normal file
@@ -0,0 +1,144 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Copyright (c) 2018, 2020 Oracle and/or its affiliates.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
=== HTTP Basic Authentication Provider
|
||||
:description: Helidon Security HTTP Basic Provider
|
||||
:keywords: helidon, security, basic
|
||||
|
||||
HTTP Basic authentication support
|
||||
|
||||
==== Setup
|
||||
|
||||
[source,xml]
|
||||
.Maven dependency
|
||||
----
|
||||
<dependency>
|
||||
<groupId>io.helidon.security.providers</groupId>
|
||||
<artifactId>helidon-security-providers-http-auth</artifactId>
|
||||
</dependency>
|
||||
----
|
||||
|
||||
[source,text]
|
||||
.Provider class name
|
||||
----
|
||||
io.helidon.security.providers.httpauth.HttpBasicAuthProvider
|
||||
----
|
||||
|
||||
[source,text]
|
||||
.Provider configuration key
|
||||
----
|
||||
http-basic-auth
|
||||
----
|
||||
|
||||
==== Example code
|
||||
https://github.com/oracle/helidon/tree/master/examples/security/outbound-override[]
|
||||
|
||||
[source,yaml]
|
||||
.Configuration example
|
||||
----
|
||||
security:
|
||||
providers:
|
||||
- http-basic-auth:
|
||||
realm: "helidon"
|
||||
users:
|
||||
- login: "john"
|
||||
password: "${CLEAR=password}"
|
||||
roles: ["admin"]
|
||||
- login: "jack"
|
||||
password: "password"
|
||||
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=password}"
|
||||
----
|
||||
|
||||
==== Configuration options
|
||||
The following table shows all configuration options of the provider and their default values
|
||||
|
||||
[cols="2,2,5"]
|
||||
|
||||
|===
|
||||
|key |default value |description
|
||||
|
||||
|`realm` |`helidon` |The realm shown in challenge when user accesses a service without authentication
|
||||
|`principal-type` |`USER` |Type of authenticated entity - either `USER` or `SERVICE`, can be used in combination with
|
||||
other authentication mechanism to authenticate both the user (as in person sitting in front of a computer)
|
||||
and a service (as in the application requesting this service on user's behalf)
|
||||
|`users` |{nbsp} |List of users when using configuration based approach. As an alternative, you can implement a java service (see below).
|
||||
|`outbound` |{nbsp} |A list of outbound configurations
|
||||
|`outbound.*.name` |{nbsp} |Required name of outbound configuration
|
||||
|`outbound.*.username` |{nbsp} |Optional username used for outbound security; if not provided, current identity is propagated
|
||||
|`outbound.*.password` |{nbsp} |Optional password used for outbound security
|
||||
|`outbound.*.transports` |any transport |An array of transports this outbound configuration should be used for
|
||||
|`outbound.*.hosts` |any host |An array of hosts this outbound configuration should be used for, can be a regular expression
|
||||
|`outbound.*.paths` |any path |An array of paths this outbound configuration should be used for (such as `/greet`), can be a regular expression
|
||||
|`outbound.*.methods` |any method |An array of HTTP methods this outbound configuration should be used for
|
||||
|`outbound.*.outbound-token` |`Authorization` header with `basic` prefix |Configuration of outbound header used to propagate
|
||||
|`outbound.*.outbound-token.header` |{nbsp} |Name of the header used to propagate the token
|
||||
|`outbound.*.outbound-token.prefix` |{nbsp} |Prefix for the header value, such as `"basic "` (only one of `prefix`, `regexp` and `format` should be defined, `regexp` wins over `prefix`, `format` wins over `regexp`)
|
||||
|`outbound.*.outbound-token.format` |{nbsp} |String format with a single parameter to create the header value, such as `"basic %1s"`
|
||||
|`outbound.*.outbound-token.regexp` |{nbsp} |Regular expression to create the header value, such as `"basic (.*)"`
|
||||
|===
|
||||
|
||||
==== How does it work?
|
||||
See https://tools.ietf.org/html/rfc7617[].
|
||||
|
||||
*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 `HttpBasicAuthProvider.EP_PROPERTY_OUTBOUND_USER`
|
||||
and `HttpBasicAuthProvider.EP_PROPERTY_OUTBOUND_PASSWORD`)
|
||||
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 Authenticaton (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.
|
||||
109
docs/shared/security/providers/http-digest-auth.adoc
Normal file
109
docs/shared/security/providers/http-digest-auth.adoc
Normal file
@@ -0,0 +1,109 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Copyright (c) 2018, 2020 Oracle and/or its affiliates.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
=== HTTP Digest Authentication Provider
|
||||
:description: Helidon Security HTTP Digest Provider
|
||||
:keywords: helidon, security, digest
|
||||
|
||||
HTTP Digest authentication support
|
||||
|
||||
==== Setup
|
||||
|
||||
[source,xml]
|
||||
.Maven dependency
|
||||
----
|
||||
<dependency>
|
||||
<groupId>io.helidon.security.providers</groupId>
|
||||
<artifactId>helidon-security-providers-http-auth</artifactId>
|
||||
</dependency>
|
||||
----
|
||||
|
||||
[source,text]
|
||||
.Provider class name
|
||||
----
|
||||
io.helidon.security.providers.httpauth.HttpDigestAuthProvider
|
||||
----
|
||||
|
||||
[source,text]
|
||||
.Provider configuration key
|
||||
----
|
||||
http-digest-auth
|
||||
----
|
||||
|
||||
==== Example code
|
||||
|
||||
[source,yaml]
|
||||
.Configuration example
|
||||
----
|
||||
security:
|
||||
providers:
|
||||
- http-digest-auth:
|
||||
realm: "helidon"
|
||||
server-secret: "${CLEAR=service-wide-secret-not-known-outside}"
|
||||
users:
|
||||
- login: "john"
|
||||
password: "${CLEAR=password}"
|
||||
roles: ["admin"]
|
||||
- login: "jack"
|
||||
password: "password"
|
||||
roles: ["user", "admin"]
|
||||
----
|
||||
|
||||
==== Configuration options
|
||||
The following table shows all configuration options of the provider and their default values
|
||||
|
||||
[cols="2,2,5"]
|
||||
|
||||
|===
|
||||
|key |default value |description
|
||||
|
||||
|`realm` |`helidon` |The realm shown in challenge when user accesses a service without authentication
|
||||
|`principal-type` |`USER` |Type of authenticated entity - either `USER` or `SERVICE`, can be used in combination with
|
||||
other authentication mechanism to authenticate both the user (as in person sitting in front of a computer)
|
||||
and a service (as in the application requesting this service on user's behalf)
|
||||
|`users` |{nbsp} |List of users when using configuration based approach. As an alternative, you can implement a java service (see below).
|
||||
|`algorithm` |`MD5` |Only `MD5` supported
|
||||
|`nonce-timeout-millis` |1 day |Number of milliseconds for the nonce timeout
|
||||
|`server-secret` |random |A string to use as a server secret - this is to use digest auth between multiple servers (e.g. when in a cluster). Used to encrypt nonce. This must not be known outside of this app, as others may create digest requests we would trust.
|
||||
|`qop` |`NONE` |only `AUTH` supported. If left empty, uses the legacy approach (older RFC version). `AUTH-INT` is not supported.
|
||||
|===
|
||||
|
||||
==== How does it work?
|
||||
See https://tools.ietf.org/html/rfc7616[].
|
||||
|
||||
*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 Authenticaton_
|
||||
|
||||
These authentication schemes
|
||||
should be _obsolete_, though they provide a very easy way to test a protected resource.
|
||||
|
||||
146
docs/shared/security/providers/http-signatures.adoc
Normal file
146
docs/shared/security/providers/http-signatures.adoc
Normal file
@@ -0,0 +1,146 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Copyright (c) 2020 Oracle and/or its affiliates.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
=== HTTP Signatures Provider
|
||||
:description: Helidon Security HTTP Signatures Provider
|
||||
:keywords: helidon, security
|
||||
|
||||
Support for HTTP Signatures.
|
||||
|
||||
==== Setup
|
||||
|
||||
[source,xml]
|
||||
.Maven dependency
|
||||
----
|
||||
<dependency>
|
||||
<groupId>io.helidon.security.providers</groupId>
|
||||
<artifactId>helidon-security-providers-http-sign</artifactId>
|
||||
</dependency>
|
||||
----
|
||||
|
||||
[source,text]
|
||||
.Provider class name
|
||||
----
|
||||
io.helidon.security.providers.httpsign.HttpSignProvider
|
||||
----
|
||||
|
||||
[source,text]
|
||||
.Provider configuration key
|
||||
----
|
||||
http-signatures
|
||||
----
|
||||
|
||||
==== Example code
|
||||
https://github.com/oracle/helidon/tree/master/examples/security/webserver-signatures[]
|
||||
|
||||
[source,yaml]
|
||||
.Configuration example
|
||||
----
|
||||
security:
|
||||
providers:
|
||||
- http-signatures:
|
||||
inbound:
|
||||
keys:
|
||||
- key-id: "service1-hmac"
|
||||
principal-name: "Service1 - HMAC signature"
|
||||
hmac.secret: "${CLEAR=somePasswordForHmacShouldBeEncrypted}"
|
||||
- key-id: "service1-rsa"
|
||||
principal-name: "Service1 - RSA signature"
|
||||
public-key:
|
||||
keystore:
|
||||
resource.path: "src/main/resources/keystore.p12"
|
||||
passphrase: "password"
|
||||
cert.alias: "service_cert"
|
||||
outbound:
|
||||
- name: "service2-hmac"
|
||||
hosts: ["localhost"]
|
||||
paths: ["/service2"]
|
||||
signature:
|
||||
key-id: "service1-hmac"
|
||||
hmac.secret: "${CLEAR=somePasswordForHmacShouldBeEncrypted}"
|
||||
- name: "service2-rsa"
|
||||
hosts: ["localhost"]
|
||||
paths: ["/service2-rsa.*"]
|
||||
signature:
|
||||
key-id: "service1-rsa"
|
||||
private-key:
|
||||
keystore:
|
||||
resource.path: "src/main/resources/keystore.p12"
|
||||
passphrase: "password"
|
||||
key.alias: "myPrivateKey"
|
||||
----
|
||||
|
||||
==== Configuration options
|
||||
The following table shows all configuration options of the provider and their default values
|
||||
|
||||
[cols="2,2,5"]
|
||||
|
||||
|===
|
||||
|key |default value |description
|
||||
|
||||
|`optional` |`false` |If set to `true`, failure to authenticate will return `ABSTAIN` result instead of `FAILURE`. This is
|
||||
an important distinction when more than one provider is used
|
||||
|`realm` | `helidon` |Realm used for challenge when request does not have a signature
|
||||
|`headers` | `[SIGNATURE,AUTHORIZATION]` |Headers to look for inbound signatures and to store outbound signatures
|
||||
|`sign-headers` | `always = ["date"]` |Headers to be signed
|
||||
|`sign-headers.*.method` |default for all methods |Method this configuration is valid for
|
||||
|`sign-headers.*.always` | {nbsp} |Array of headers to be always required in the request signature
|
||||
|`sign-headers.*.if-present` |{nbsp} |Array of headers to be part of the signatures if present in the request
|
||||
|`inbound` |{nbsp} |Configuration of inbound traffic for authenticating incoming requests
|
||||
|`inbound.keys` |{nbsp} |Configuration of signature keys to verify incoming requests
|
||||
|`inbound.keys.*.key-id` |{nbsp} |Key id as used in inbound signature to find the correct certificate/hmac configuration to verify the signature
|
||||
|`inbound.keys.*.principal-name` |{nbsp} |The principal name (or user name) asserted when the signature is valid
|
||||
|`inbound.keys.*.principal-type` |`SERVICE` |The type of principal to assert (can be `USER`)
|
||||
|`inbound.keys.*.algorithm` |according to other configuration |`hmac-sha256` or `rsa-sha256` is assumed if other configuration options for that type are set
|
||||
|`inbound.keys.*.hmac.secret` |{nbsp} |Secret shared by the service that signed the request and this service for `hmac-sha256` algorithm
|
||||
|`inbound.keys.*.public-key` |{nbsp} |Public key configuration, implies `rsa-sha256` algorithm
|
||||
|`inbound.keys.*.public-key.keystore` |{nbsp} |Keystore configuration for public key - full configuration as defined by `KeyStore` class
|
||||
|`outbound` |{nbsp} |A list of outbound configurations
|
||||
|`outbound.*.name` |{nbsp} |Required name of outbound configuration
|
||||
|`outbound.*.username` |{nbsp} |Optional username used for outbound security; if not provided, current identity is propagated
|
||||
|`outbound.*.password` |{nbsp} |Optional password used for outbound security
|
||||
|`outbound.*.transports` |any transport |An array of transports this outbound configuration should be used for
|
||||
|`outbound.*.hosts` |any host |An array of hosts this outbound configuration should be used for, can be a regular expression
|
||||
|`outbound.*.paths` |any path |An array of paths this outbound configuration should be used for (such as `/greet`), can be a regular expression
|
||||
|`outbound.*.methods` |any method |An array of HTTP methods this outbound configuration should be used for
|
||||
|`outbound.*.signature` |{nbsp} |Configuration related to outbound signature configuration
|
||||
|`outbound.*.signature.key-id` |{nbsp} |Key id to use in the outbound signature (to map to appropriate public key in target service's configuration)
|
||||
|`outbound.*.signature.hmac.secret` |{nbsp} |Shared secret for hmac
|
||||
|`outbound.*.signature.private-key` |{nbsp} |Private key configuration for rsa based signatures
|
||||
|`outbound.*.signature.private-key.keystore` |{nbsp} |Keystore configuration for private key - full configuration as defined by `KeyStore` class
|
||||
|===
|
||||
|
||||
==== 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
|
||||
94
docs/shared/security/providers/idcs-role-mapper.adoc
Normal file
94
docs/shared/security/providers/idcs-role-mapper.adoc
Normal file
@@ -0,0 +1,94 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Copyright (c) 2020 Oracle and/or its affiliates.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
=== IDCS Role Mapper
|
||||
:description: Helidon Security IDCS Role Mapper Provider
|
||||
:keywords: helidon, security, idcs
|
||||
|
||||
A role mapper to retrieve roles from Oracle IDCS.
|
||||
|
||||
==== Setup
|
||||
|
||||
[source,xml]
|
||||
.Maven dependency
|
||||
----
|
||||
<dependency>
|
||||
<groupId>io.helidon.security.providers</groupId>
|
||||
<artifactId>helidon-security-providers-idcs-mapper</artifactId>
|
||||
</dependency>
|
||||
----
|
||||
|
||||
[source,text]
|
||||
.Provider class name
|
||||
----
|
||||
io.helidon.security.providers.idcs.mapper.IdcsRoleMapperProvider
|
||||
----
|
||||
|
||||
[source,text]
|
||||
.Provider configuration key
|
||||
----
|
||||
idcs-role-mapper
|
||||
----
|
||||
|
||||
==== Example code
|
||||
https://github.com/oracle/helidon/tree/master/examples/security/idcs-login/[]
|
||||
|
||||
[source,yaml]
|
||||
.Configuration example
|
||||
----
|
||||
security:
|
||||
providers:
|
||||
- idcs-role-mapper:
|
||||
multitenant: false
|
||||
oidc-config:
|
||||
client-id: "client-id"
|
||||
client-secret: "client-secret"
|
||||
identity-uri: "IDCS identity server address"
|
||||
----
|
||||
|
||||
==== Configuration options
|
||||
The following table shows all configuration options of the provider and their default values
|
||||
|
||||
[cols="2,2,5"]
|
||||
|
||||
|===
|
||||
|key |default value |description
|
||||
|
||||
|`multitenant` |`true` |Whether to support multi-tenancy with this provider
|
||||
|`idcs-tenant-handler` |Header `X-USER-IDENTITY-SERVICE-GUID` |Multi-tenant specific `TokenHandler` configuration to retrieve the tenant id
|
||||
|`idcs-app-name-handler` |Header `X-RESOURCE-SERVICE-INSTANCE-IDENTITY-APPNAME` |Multi-tenant specific `TokenHandler` configuration to retrieve the application name
|
||||
|`cache-config` |{nbsp} |Configuration of cache of roles for subjects
|
||||
|`cache-config.cache-enabled` |`true` |Possibility to disable the cache altogether
|
||||
|`cache-config.max-size` |`100_000` |Maximal number of records in the cache
|
||||
|`cache-config.cache-timeout-millis` |1 hour |Cache timeout in milliseconds
|
||||
|`cache-config.cache-evict-delay-millis` |1 minute |How long to wait before starting the first eviction process
|
||||
|`cache-config.cache-evict-period-millis` |5 minutes |Period of running the eviction process
|
||||
|`cache-config.parallelism-threshold` |`10_000` |Threshold as used by `ConcurrentHashMap.forEachKey`
|
||||
|`cache-config.evictor-class` |{nbsp} |Implementation of `BiFunction` that receives key and value, and returns `true` for records that should be removed
|
||||
from the cache. Eviction mechanism should be fast, as it is called within methods of `ConcurrentHashMap`
|
||||
|`subject-types` |`USER` |Can use `USER` and/or `SERVICE`
|
||||
|`default-idcs-subject-type` |`user` |Default subject type to use when requesting roles, can be `user` or `client`
|
||||
|`oidc-config` |{nbsp} |`OidcConfig` configuration, except `validate-with-jwk` is set to `false`,
|
||||
and `server-type` is set to `idcs`
|
||||
|===
|
||||
|
||||
==== 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).
|
||||
|
||||
120
docs/shared/security/providers/jwt.adoc
Normal file
120
docs/shared/security/providers/jwt.adoc
Normal file
@@ -0,0 +1,120 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Copyright (c) 2020 Oracle and/or its affiliates.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
=== JWT Provider
|
||||
:description: Helidon Security JWT Provider
|
||||
:keywords: helidon, security, jwt
|
||||
|
||||
JWT token authentication and outbound security provider.
|
||||
|
||||
==== Setup
|
||||
|
||||
[source,xml]
|
||||
.Maven dependency
|
||||
----
|
||||
<dependency>
|
||||
<groupId>io.helidon.security.providers</groupId>
|
||||
<artifactId>helidon-security-providers-jwt</artifactId>
|
||||
</dependency>
|
||||
----
|
||||
|
||||
[source,text]
|
||||
.Provider class name
|
||||
----
|
||||
io.helidon.security.providers.jwt.JwtProvider
|
||||
----
|
||||
|
||||
[source,text]
|
||||
.Provider configuration key
|
||||
----
|
||||
jwt
|
||||
----
|
||||
|
||||
==== Example code
|
||||
https://github.com/oracle/helidon/tree/master/examples/security/outbound-override[]
|
||||
|
||||
[source,yaml]
|
||||
.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"
|
||||
----
|
||||
|
||||
==== Configuration options
|
||||
The following table shows all configuration options of the provider and their default values
|
||||
|
||||
[cols="2,2,5"]
|
||||
|
||||
|===
|
||||
|key |default value |description
|
||||
|
||||
|`optional` |`false` |If set to `true`, failure to authenticate will return `ABSTAIN` result instead of `FAILURE`. This is
|
||||
an important distinction when more than one provider is used
|
||||
|`authenticate` |`true` |Whether to attempt authentication
|
||||
|`propagate` |`true` |Whether to attempt identity propagation/JWT creation
|
||||
|`principal-type` |`USER` |Whether we authenticate a user or a service (other option is SERVICE)
|
||||
|`atn-token` | |A group for configuring authentication of the request
|
||||
|`atn-token.verify-signature` |`true` |Whether to verify signature in incoming JWT. If disabled, _ANY_ JWT will be accepted
|
||||
|`atn-token.jwt-audience` |{nbsp} |Expected audience of the JWT. If not defined, any audience is accepted (and we may accept JWT not inteded for us)
|
||||
|`atn-token.jwk.resource.*` |{nbsp} |Configuration of the JWK to obtain key(s) to validate signatures of inbound token. The JWK should contain public keys. This may be: jwk.resource.path, jwk.resource.resource-path, jwk.resource.url, jwk.resource.content-plain (actual JSON string), jwk.resource.content (base64)
|
||||
|`atn-token.handler` |`Authorization` header with `bearer ` prefix |A handler configuration for inbound token - e.g. how to extract it
|
||||
|`atn-token.handler.header` |{nbsp} |Name of a header the token is expected in
|
||||
|`atn-token.handler.prefix` |{nbsp} |Prefix before the token value (optional)
|
||||
|`atn-token.handler.regexp` |{nbsp} |Regular expression to obtain the token, first matching group is used (optional)
|
||||
|`sign-token` |{nbsp} |A group for configuring outbound security
|
||||
|`sign-token.jwk.resource.*` |{nbsp} |Configuration of the JWK to use when generating tokens (follows same rules as atn-token.jwk above), this JWK must contain private keys when using asymmetric ciphers
|
||||
|`sign-token.jwt-issuer` |{nbsp} |When we issue a new token, this is the issuer to be placed into it (validated by target service)
|
||||
|`sign-token.outbound` |{nbsp} |A group for configuring outbound rules (based on transport, host and.or path)
|
||||
|`sign-token.outbound.*.name` |{nbsp} |A short descriptive name for configured target service(s)
|
||||
|`sign-token.outbound.*.transports` |any |An array of transports this outbound matches (e.g. https)
|
||||
|`sign-token.outbound.*.hosts` |any |An array of hosts this outbound matches, may use * as a wild-card (e.g. *.oracle.com)
|
||||
|`sign-token.outbound.*.paths` |any |An array of paths on the host this outbound matches, may use * as a wild-card (e.g. /some/path/*)
|
||||
|`sign-token.outbound.*.outbound-token` |`Authorization` header with `bearer ` prefix |Configuration of outbound token handler (same as atn-token.handler)
|
||||
|`sign-token.outbound.*.outbound-token.format` |{nbsp} |Java text format for generating the value of outbound token header (e.g. "bearer %1$s")
|
||||
|`sign-token.outbound.*.jwk-kid` |{nbsp} |If this key is defined, we are generating a new token, otherwise we propagate existing. Defines the key id of a key definition in the JWK file to use for signing the outbound token
|
||||
|`sign-token.outbound.*.jwt-kid` |{nbsp} |A key to use in the generated JWT - this is for the other service to locate the verification key in their JWK
|
||||
|`sign-token.outbound.*.jwt-audience` |{nbsp} |Audience this key is generated for (e.g. http://www.example.org/api/myService) - validated by the other service
|
||||
|`sign-token.outbound.*.jwt-not-before-seconds` |`5` |Makes this key valid this amount of seconds into the past. Allows a certain time-skew for the generated token to be valid before current time (e.g. when we expect a certain misalignment of clocks)
|
||||
|`sign-token.outbound.*.jwt-validity-seconds` |1 day |Token validity in seconds
|
||||
|===
|
||||
|
||||
==== 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.
|
||||
|
||||
|
||||
143
docs/shared/security/providers/oidc.adoc
Normal file
143
docs/shared/security/providers/oidc.adoc
Normal file
@@ -0,0 +1,143 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Copyright (c) 2018, 2020 Oracle and/or its affiliates.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
:description: Helidon Security OIDC Provider
|
||||
:keywords: helidon, security, oidc
|
||||
|
||||
[source,text]
|
||||
.Provider class name
|
||||
----
|
||||
io.helidon.security.providers.oidc.OidcProvider
|
||||
----
|
||||
|
||||
[source,text]
|
||||
.Provider configuration key
|
||||
----
|
||||
oidc
|
||||
----
|
||||
|
||||
==== Example code
|
||||
https://github.com/oracle/helidon/tree/master/examples/security/idcs-login[]
|
||||
|
||||
[source,yaml]
|
||||
.Configuration example
|
||||
----
|
||||
security:
|
||||
providers:
|
||||
- oidc:
|
||||
client-id: "client-id-of-this-service"
|
||||
client-secret: "${CLEAR=client-secret-of-this-service}"
|
||||
identity-uri: "http://your-tenant.identity-server.com"
|
||||
frontend-uri: "http://my-service:8080"
|
||||
audience: "http://my-service"
|
||||
outbound:
|
||||
- name: "internal-services"
|
||||
hosts: ["*.example.org"]
|
||||
outbound-token:
|
||||
header: "X-Internal-Auth"
|
||||
----
|
||||
|
||||
==== Configuration options
|
||||
The following table shows all configuration options of the provider and their default values
|
||||
|
||||
[cols="2,2,5"]
|
||||
|
||||
|===
|
||||
|key |default value |description
|
||||
|
||||
|`client-id` |{nbsp} |Client ID as generated by identity server
|
||||
|`client-secret` |{nbsp} |Client secret as generated by identity server
|
||||
|`identity-uri` |{nbsp} |URI of the identity server, base used to retrieve OIDC metadata
|
||||
|`frontend-uri` |{nbsp} |Full URI of this service for redirects back from OIDC server
|
||||
|`issuer` |`issuer` from OIDC metadata |Issuer of token - each JWT is validated to check the issuer
|
||||
|`audience` | {nbsp} |Audience of a token - each JWT is validated to check the audience
|
||||
|`proxy-protocol` |`http` |Proxy protocol to use when proxy is used
|
||||
|`proxy-host` |`null` |Proxy host to use. When defined, triggers usage of proxy for HTTP requests
|
||||
|`proxy-port` |`80` |Port of the proxy server to use
|
||||
|`redirect-uri` |`/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.
|
||||
|`scope-audience` |empty string |Audience of the scope required by this application. This is prefixed to the scope name when requesting scopes from the identity server.
|
||||
|`cookie-use` |`true` |Whether to use cookie to store JWT. If used, redirects happen only in case the user is not authenticated or has insufficient scopes
|
||||
|`cookie-name` |`JSESSIONID` |Name of the cookie
|
||||
|`cookie-domain` |{nbsp} |Domain the cookie is valid for. Not used by default
|
||||
|`cookie-path` |`/` |Path the cookie is valid for.
|
||||
|`cookie-max-age-seconds` |{nsbp} |When using cookie, used to set MaxAge attribute of the cookie, defining how long the cookie is valid.
|
||||
|`cookie-http-only` |`true` |When using cookie, if set to true, the HttpOnly attribute will be configured.
|
||||
|`cookie-secure` |`false` |When using cookie, if set to true, the Secure attribute will be configured.
|
||||
|`cookie-same-site` |`Lax` |When using cookie, used to set the SameSite cookie value. Can be "Strict" or "Lax". Setting this to "Strict" will result in infinite redirects when calling OIDC on a different host.
|
||||
|`query-param-use` |`false` |Whether to expect JWT in a query parameter
|
||||
|`query-param-name` |`accessToken` |Name of a query parameter that contains the JWT token when parameter is used.
|
||||
|`header-use` |`false` |Whether to expect JWT in a header field.
|
||||
|`header-token` |`Authorization` header with prefix `bearer` |A TokenHandler configuration to process header containing a JWT
|
||||
|`oidc-metadata-well-known` |`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` |`identity-uri/.well-known/openid-configuration` |Resource configuration for OIDC Metadata containing endpoints to various identity services, as well as information about the identity server. See Resource.create(io.helidon.config.Config)
|
||||
|`token-endpoint-uri` |`token_endpoint` in OIDC metadata, or `identity-url/oauth2/v1/token` if not available |URI of a token endpoint used to obtain a JWT based on the authentication code.
|
||||
|`authorization-endpoint-uri` |"authorization_endpoint" in OIDC metadata, or `identity-uri/oauth2/v1/authorize` if not available |URI of an authorization endpoint used to redirect users to for logging-in.
|
||||
|`validate-with-jwk` |`true` |When true - validate against jwk defined by "sign-jwk", when false validate JWT through OIDC Server endpoint "validation-endpoint-uri"
|
||||
|`sign-jwk.resource` |"jwks-uri" in OIDC metadata, or `identity-uri/admin/v1/SigningCert/jwk` if not available, only needed when jwt validation is done by us |A resource pointing to JWK with public keys of signing certificates used to validate JWT. See Resource.create(io.helidon.config.Config)
|
||||
|`introspect-endpoint-uri` |"introspection_endpoint" in OIDC metadata, or `identity-uri/oauth2/v1/introspect` |When validate-with-jwk is set to "false", this is the endpoint used
|
||||
|`base-scopes` |`openid` |Configure scopes to be requested by default. If the scope has a qualifier, it must be included here
|
||||
|`redirect` |`true` |Whether to redirect to identity server when authentication failed.
|
||||
|`realm` |`helidon` |Realm returned in HTTP response if redirect is not enabled or possible.
|
||||
|`redirect-attempt-param` |`h_ra` |Query parameter holding the number of times we redirected to an identity server. Customizable to prevent conflicts with application parameters
|
||||
|`max-redirects` |`5` |Maximal number of times we can redirect to an identity server. When the number is reached, no further redirects happen and the request finishes with an error (status 401)
|
||||
|`server-type` |{nbsp} |Type of identity server. Currently supported is idcs or not configured (for default).
|
||||
|`propagate` |{nbsp} |Whether to propagate the token we have. Defaults to `false` unless an outbound configuration is defined
|
||||
|`outbound` |{nbsp} |A list of outbound configurations
|
||||
|`outbound.*.name` |{nbsp} |Required name of outbound configuration
|
||||
|`outbound.*.transports` |any transport |An array of transports this outbound configuration should be used for
|
||||
|`outbound.*.hosts` |any host |An array of hosts this outbound configuration should be used for, can be a regular expression
|
||||
|`outbound.*.paths` |any path |An array of paths this outbound configuration should be used for (such as `/greet`), can be a regular expression
|
||||
|`outbound.*.methods` |any method |An array of HTTP methods this outbound configuration should be used for
|
||||
|`outbound.*.outbound-token` |`Authorization` header with `bearer` prefix |Configuration of outbound header used to propagate
|
||||
|`outbound.*.outbound-token.header` |{nbsp} |Name of the header used to propagate the token
|
||||
|`outbound.*.outbound-token.prefix` |{nbsp} |Prefix for the header value, such as `"bearer"` (only one of `prefix`, `regexp` and `format` should be defined, `regexp` wins over `prefix`, `format` wins over `regexp`)
|
||||
|`outbound.*.outbound-token.format` |{nbsp} |String format with a single parameter to create the header value, such as `"bearer %1s"`
|
||||
|`outbound.*.outbound-token.regexp` |{nbsp} |Regular expression to create the header value, such as `"bearer (.*)"`
|
||||
|===
|
||||
|
||||
==== 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
|
||||
|
||||
|
||||
73
docs/shared/security/providers/provider-template.adoc
Normal file
73
docs/shared/security/providers/provider-template.adoc
Normal file
@@ -0,0 +1,73 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Copyright (c) 2020 Oracle and/or its affiliates.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
=== Provider
|
||||
:description: Helidon Security ... Provider
|
||||
:keywords: helidon, security
|
||||
|
||||
Short description
|
||||
|
||||
==== Setup
|
||||
|
||||
[source,xml]
|
||||
.Maven dependency
|
||||
----
|
||||
<dependency>
|
||||
<groupId>io.helidon.security.providers</groupId>
|
||||
<artifactId>helidon-security-providers-</artifactId>
|
||||
</dependency>
|
||||
----
|
||||
|
||||
[source,text]
|
||||
.Provider class name
|
||||
----
|
||||
io.helidon.security.providers.
|
||||
----
|
||||
|
||||
[source,text]
|
||||
.Provider configuration key
|
||||
----
|
||||
provider-config-key
|
||||
----
|
||||
|
||||
==== Example code
|
||||
https://github.com/oracle/helidon/tree/master/examples/security/[]
|
||||
|
||||
[source,yaml]
|
||||
.Configuration example
|
||||
----
|
||||
security:
|
||||
providers:
|
||||
- provider:
|
||||
key: "value"
|
||||
----
|
||||
|
||||
==== Configuration options
|
||||
The following table shows all configuration options of the provider and their default values
|
||||
|
||||
[cols="2,2,5"]
|
||||
|
||||
|===
|
||||
|key |default value |description
|
||||
|
||||
|`key` |{nbsp} |Description
|
||||
|===
|
||||
|
||||
==== How does it work?
|
||||
Detailed description
|
||||
|
||||
Reference in New Issue
Block a user