Skip to content

Commit

Permalink
Merge pull request #37781 from MichalMaler/Security-review-by-Mickey
Browse files Browse the repository at this point in the history
Security guide writer's review
  • Loading branch information
sberyozkin authored Dec 16, 2023
2 parents 02a2f75 + 42750ed commit 7cf3e4e
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 42 deletions.
15 changes: 9 additions & 6 deletions docs/src/main/asciidoc/security-authentication-mechanisms.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ include::{generated-dir}/config/quarkus-vertx-http-config-group-auth-runtime-con
Quarkus provides mutual TLS (mTLS) authentication so that you can authenticate users based on their X.509 certificates.

To use this authentication method, you must first enable SSL/TLS for your application.
For more information, see the xref:http-reference.adoc#ssl[Supporting secure connections with SSL/TLS] section of the Quarkus "HTTP reference" guide.
For more information, see the xref:http-reference.adoc#ssl[Supporting secure connections with SSL/TLS] section of the Quarkus "HTTP reference" guide.

After your application accepts secure connections, the next step is to configure the `quarkus.http.ssl.certificate.trust-store-file` property with the name of that file that holds all the certificates your application trusts. The specified file also includes information about how your application asks for certificates when a client, such as a browser or other service, tries to access one of its protected resources.

Expand All @@ -198,11 +198,12 @@ quarkus.http.insecure-requests=disabled <5>
----
<1> The keystore where the server's private key is located.
<2> The truststore from which the trusted certificates are loaded.
<3> With this value set to `required`, the server requires certificates from clients.
To relax this requirement so that the server accepts requests without a certificate, set the value to `REQUEST`.
This option is useful when you are also supporting authentication methods other than mTLS.
<3> With the value set to `required`, the server demands client certificates.
Set the value to `REQUEST` to allow the server to accept requests without a certificate.
This setting is beneficial when supporting authentication methods besides mTLS.
<4> Defines a policy where only authenticated users should have access to resources from your application.
<5> Optionally,explicitly disable the plain HTTP protocol, and consequently require all requests to be made over HTTPS. If `quarkus.http.ssl.client-auth` is set to `required`, the `quarkus.http.insecure-requests` property is automatically set to `disabled`.
<5> You can explicitly disable the plain HTTP protocol, thus requiring all requests to use HTTPS.
When you set `quarkus.http.ssl.client-auth` to `required`, the system automatically sets `quarkus.http.insecure-requests` to `disabled`.

When the incoming request matches a valid certificate in the truststore, your application can obtain the subject by injecting a `SecurityIdentity` as follows:

Expand Down Expand Up @@ -263,6 +264,7 @@ OIDC enables client applications to verify the identity of a user based on the a

The Quarkus `quarkus-oidc` extension provides a reactive, interoperable, multitenant-enabled OIDC adapter that supports Bearer token and Authorization Code Flow authentication mechanisms.
The Bearer token authentication mechanism extracts the token from the HTTP Authorization header.

The Authorization Code Flow mechanism redirects the user to an OIDC provider to authenticate the user's identity.
After the user is redirected back to Quarkus, the mechanism completes the authentication process by exchanging the provided code that was granted for the ID, access, and refresh tokens.

Expand All @@ -285,7 +287,7 @@ For more information about OIDC authentication and authorization methods that yo
|Authorization Code Flow authentication mechanism|xref:security-oidc-code-flow-authentication.adoc[OpenID Connect (OIDC) Authorization Code Flow mechanism]
|OIDC and SAML Identity broker|xref:security-oidc-code-flow-authentication.adoc#oidc-saml-broker[OpenID Connect (OIDC) Authorization Code Flow and SAML Identity broker]
|Multiple tenants that can support the Bearer token authentication or Authorization Code Flow mechanisms|xref:security-openid-connect-multitenancy.adoc[Using OpenID Connect (OIDC) multi-tenancy]
|Securing Quarkus with commonly-used OpenID Connect providers|xref:security-openid-connect-providers.adoc[Configuring well-known OpenID Connect providers]
|Securing Quarkus with commonly used OpenID Connect providers|xref:security-openid-connect-providers.adoc[Configuring well-known OpenID Connect providers]
|Using Keycloak to centralize authorization |xref:security-keycloak-authorization.adoc[Using OpenID Connect (OIDC) and Keycloak to centralize authorization]
|Configuring Keycloak programmatically |xref:security-keycloak-admin-client.adoc[Using the Keycloak admin client]
|====
Expand Down Expand Up @@ -339,6 +341,7 @@ For more information, see the xref:security-jwt.adoc[Using JWT RBAC] guide.

`quarkus-elytron-security-oauth2` provides an alternative to the Quarkus `quarkus-oidc` Bearer token authentication mechanism extension.
`quarkus-elytron-security-oauth2` is based on `Elytron` and is primarily intended for introspecting opaque tokens remotely.

For more information, see the Quarkus xref:security-oauth2.adoc[Using OAuth2] guide.

[[oidc-jwt-oauth2-comparison]]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ include::_attributes.adoc[]
:topics: security,authorization,http,rest
:extensions: io.quarkus:quarkus-vertx-http,io.quarkus:quarkus-resteasy-reactive,io.quarkus:quarkus-resteasy

Quarkus has an integrated pluggable web security layer.
If security is enabled, all HTTP requests have a permission check performed to verify that they are allowed to continue.
Therefore, you cannot use `@PermitAll` to open a path if the path is blocked by the `quarkus.http.auth.` configuration.
Quarkus incorporates a pluggable web security layer.
When security is active, the system performs a permission check on all HTTP requests to determine if they should proceed.

Using `@PermitAll` will not open a path if the path is restricted by the `quarkus.http.auth.` configuration.
To ensure specific paths are accessible, appropriate configurations must be made within the Quarkus security settings.

[NOTE]
====
Expand All @@ -26,7 +28,7 @@ xref:security-customization.adoc#security-identity-customization[Security Identi
[[authorization-using-configuration]]
== Authorization using configuration

Permissions are defined in the Quarkus configuration using permission sets, each specifying a policy for access control.
Permissions are defined in the Quarkus configuration by permission sets, each specifying a policy for access control.

.{project-name} policies summary
[options="header"]
Expand Down Expand Up @@ -68,7 +70,11 @@ It is an exact path match because it does not end with `*`.
<3> This permission set references the previously defined policy.
`roles1` is an example name; you can call the permission sets whatever you want.

WARNING: The `/forbidden` exact path in the example above will not secure the `/forbidden/` path. Don't forget to add new exact path for the `/forbidden/` path.
[WARNING]
====
The exact path `/forbidden` in the example will not secure the `/forbidden/` path.
It is necessary to add a new exact path for the `/forbidden/` path to ensure proper security coverage.
====

=== Custom HttpSecurityPolicy

Expand Down Expand Up @@ -141,8 +147,11 @@ For that reason, a path like `/public-info` is not matched by this pattern.

The request is rejected if it matches one or more permission sets based on the path but none of the required methods.

TIP: Given the preceding permission set, `GET /public/foo` would match both the path and method and therefore be allowed.
[TIP]
====
Given the preceding permission set, `GET /public/foo` would match both the path and method and therefore be allowed.
In contrast, `POST /public/foo` would match the path but not the method, and, therefore, be rejected.
====

[[matching-multiple-paths]]
=== Matching multiple paths: longest path wins
Expand All @@ -160,13 +169,17 @@ quarkus.http.auth.permission.deny1.paths=/public/forbidden-folder/*
quarkus.http.auth.permission.deny1.policy=deny
----

TIP: Given the preceding permission set, `GET /public/forbidden-folder/foo` would match both permission sets' paths.
[TIP]
====
Given the preceding permission set, `GET /public/forbidden-folder/foo` would match both permission sets' paths.
However, because the longer path matches the path of the `deny1` permission set, `deny1` is chosen, and the request is rejected.
====

[NOTE]
====
Subpath permissions always win against the root path permissions, as explained in the preceding `deny1` versus `permit1` permission example.
Here is another example showing subpath permission allowing a public resource access with the root path permission requiring the authorization:
Subpath permissions precede root path permissions, as the `deny1` versus `permit1` permission example previously illustrated.
This rule is further exemplified by a scenario where subpath permission allows access to a public resource while the root path permission necessitates authorization.
[source,properties]
----
Expand All @@ -181,14 +194,15 @@ quarkus.http.auth.permission.public.policy=permit

=== Matching multiple sub-paths: longest path to the `*` wildcard wins

Previous examples shown how you can match all sub-paths when a path ends with the `$$*$$` wildcard.
The `$$*$$` wildcard can also be used in the middle of the path, in which case it represents exactly one path segment.
You can't combine this wildcard with any other path segment character, therefore the `$$*$$` wildcard will always be
enclosed with path separators as in the `/public/$$*$$/about-us` path.
Previous examples demonstrated matching all sub-paths when a path concludes with the `$$*$$`
wildcard.

What happens if multiple path patterns matches same request path?
Matching is always done on the "longest sub-path to the `$$*$$` wildcard wins" basis.
Every path segment character is considered more specific than the `$$*$$` wildcard.
This wildcard also applies in the middle of a path, representing a single path segment.
It cannot be mixed with other path segment characters; thus, path separators always enclose the `$$*$$` wildcard, as seen in the `/public/`$$*$$`/about-us` path.

When several path patterns correspond to the same request path, the system selects the longest sub-path leading to the `$$*$$` wildcard.
In this context, every path segment character is more specific than the `$$*$$`
wildcard.

Here is a simple example:

Expand Down Expand Up @@ -249,9 +263,11 @@ quarkus.http.auth.permission.deny1.policy=deny

[NOTE]
====
Given the preceding permission set, `GET /public/foo` would match the paths of both permission sets, but because it fits the explicit method of the `permit1` permission set, `permit1` is chosen, and the request is accepted.
The preceding permission set shows that `GET /public/foo` matches the paths of both permission sets.However, it specifically aligns with the explicit method of the `permit1` permission set.Therefore, `permit1` is selected, and the request is accepted.
Conversely, `PUT /public/foo` would not match the method permissions of `permit1`, so `deny1` would be activated and reject the request.
In contrast, `PUT /public/foo` does not match the method permissions of `permit1`. As a result, `deny1` is activated, leading to the rejection of the request.
====

=== Matching multiple paths and methods: both win
Expand Down Expand Up @@ -329,8 +345,8 @@ quarkus.http.auth.permission.permit1.paths=${quarkus.http.root-path}/public/*,${

A leading slash changes how the configured permission path is interpreted.
The configured URL is used as-is, and paths are not adjusted if the value of `quarkus.http.root-path` changes.
For example:

.Example:
[source,properties]
----
quarkus.http.auth.permission.permit1.paths=/public/*,css/*,js/*,robots.txt
Expand All @@ -343,8 +359,8 @@ For more information, see link:https://quarkus.io/blog/path-resolution-in-quarku
[[map-security-identity-roles]]
=== Map `SecurityIdentity` roles

Winning role-based policy can map the `SecurityIdentity` roles to the deployment specific roles.
These roles can later be used for endpoint authorization with the `@RolesAllowed` annotation.
Winning role-based policy can map the `SecurityIdentity` roles to the deployment-specific roles.
These roles are then applicable for endpoint authorization by using the @RolesAllowed annotation.

[source,properties]
----
Expand All @@ -368,7 +384,7 @@ s| @DenyAll | Specifies that no security roles are allowed to invoke the specifi
s| @PermitAll | Specifies that all security roles are allowed to invoke the specified methods.

`@PermitAll` lets everybody in, even without authentication.
s| @RolesAllowed | Specifies the list of security roles permitted to access methods in an application.
s| @RolesAllowed | Specifies the list of security roles allowed to access methods in an application.

As an equivalent to `@RolesAllowed("**")`, {project-name} also provides the `io.quarkus.security.Authenticated` annotation that permits any authenticated user to access the resource.
|===
Expand Down Expand Up @@ -518,7 +534,7 @@ It is possible to use multiple expressions in the role definition.
<3> This `/subject/user` endpoint requires an authenticated user that has been granted the role "User" through the use of the `@RolesAllowed("${customer:User}")` annotation because we did not set the configuration property `customer`.
<4> In production, this `/subject/secured` endpoint requires an authenticated user with the `User` role.
In development mode, it allows any authenticated user.
<5> Property expression `all-roles` will be treated as a collection type `List`, therefore the endpoint will be accessible for roles `Administrator`, `Software`, `Tester` and `User`.
<5> Property expression `all-roles` will be treated as a collection type `List`, therefore, the endpoint will be accessible for roles `Administrator`, `Software`, `Tester` and `User`.

[[permission-annotation]]
=== Permission annotation
Expand Down Expand Up @@ -802,8 +818,8 @@ Because `MediaLibrary` is the `TvLibrary` class parent, a user with the `admin`
TIP: The `/library/*` path can be tested from a Keycloak provider Dev UI page, because the user `alice` which is created
automatically by the xref:security-openid-connect-dev-services.adoc[Dev Services for Keycloak] has an `admin` role.

The examples provided so far use role-to-permission mapping.
You can also add permissions to the `SecurityIdentity` instance programmatically.
The examples provided so far demonstrate role-to-permission mapping.
It is also possible to programmatically add permissions to the `SecurityIdentity` instance.
In the following example, xref:security-customization.adoc#security-identity-customization[`SecurityIdentity` is customized] to add the same permission that was previously granted with the HTTP role-based policy.

.Example of adding the `LibraryPermission` programmatically to `SecurityIdentity`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ For information about other methods that you can use to configure the required u
+
[IMPORTANT]
====
Configuring user names, secrets, and roles in the `application.properties` file is only suitable for testing scenarios.
If you are securing a production application, always use a database to store this information.
Configuring user names, secrets, and roles in the `application.properties` file is appropriate only for testing scenarios.
For securing a production application, it is crucial to use a database to store this information.
====

== Next steps
Expand Down
16 changes: 7 additions & 9 deletions docs/src/main/asciidoc/security-basic-authentication.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,19 @@ include::_attributes.adoc[]
:extensions: io.quarkus:quarkus-vertx-http,io.quarkus:quarkus-elytron-security-jdbc,io.quarkus:quarkus-elytron-security-ldap,io.quarkus:quarkus-security-jpa-reactive

HTTP Basic authentication is one of the least resource-demanding techniques that enforce access controls to web resources.
You can secure your Quarkus application endpoints with HTTP Basic authentication.
Quarkus provides a built-in authentication mechanism for Basic authentication.
You can secure your Quarkus application endpoints by using HTTP Basic authentication.
Quarkus includes a built-in authentication mechanism for Basic authentication.

Basic authentication uses fields in the HTTP header and does not require HTTP cookies, session identifiers, or login pages.
Basic authentication uses fields in the HTTP header and does not rely on HTTP cookies, session identifiers, or login pages.

== Authorization header

An HTTP user agent, for example, a web browser, uses an `Authorization` header to provide a username and password in each HTTP request.
The header is specified as `Authorization: Basic <credentials>`, where credentials are the Base64 encoding of the user ID and password joined by a colon, as shown in the following example.

====
.Example
An HTTP user agent, like a web browser, uses an `Authorization` header to provide a username and password in each HTTP request.
The header is specified as `Authorization: Basic <credentials>`, where credentials are the Base64 encoding of the user ID and password, joined by a colon.

.Example:
If the user name is `Alice` and the password is `secret`, the HTTP authorization header would be `Authorization: Basic QWxjZTpzZWNyZXQ=`, where `QWxjZTpzZWNyZXQ=` is a Base64 encoded representation of the `Alice:secret` string.
====


The Basic authentication mechanism does not provide confidentiality protection for the transmitted credentials.
The credentials are merely encoded with Base64 when in transit, and not encrypted or hashed in any way.
Expand Down

0 comments on commit 7cf3e4e

Please sign in to comment.