Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Docs security JPA small enhancement and fix #37799

Merged
merged 1 commit into from
Dec 19, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 31 additions & 6 deletions docs/src/main/asciidoc/security-jpa.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,21 @@
https://github.com/quarkusio/quarkus/tree/main/docs/src/main/asciidoc
////
[id="security-jpa"]
= Quarkus Security with Jakarta Persistence

Check warning on line 7 in docs/src/main/asciidoc/security-jpa.adoc

View workflow job for this annotation

GitHub Actions / Linting with Vale

[vale] reported by reviewdog 🐶 [Quarkus.Headings] Use sentence-style capitalization in 'Quarkus Security with Jakarta Persistence'. Raw Output: {"message": "[Quarkus.Headings] Use sentence-style capitalization in 'Quarkus Security with Jakarta Persistence'.", "location": {"path": "docs/src/main/asciidoc/security-jpa.adoc", "range": {"start": {"line": 7, "column": 3}}}, "severity": "INFO"}
include::_attributes.adoc[]
:categories: security
:summary: This guide explains how your application can use Jakarta Persistence to store users identities.
:topics: security,identity-providers,sql,database,jpa,jdbc
:extensions: io.quarkus:quarkus-security-jpa-reactive

Quarkus provides a Jakarta Persistence (formerly known as JPA) identity provider, similar to the xref:security-jdbc.adoc[JDBC identity provider], suitable for use with the xref:security-basic-authentication.adoc[Basic] and xref:security-authentication-mechanisms.adoc#form-auth[Form-based] Quarkus Security mechanisms, which require a combination of username and password credentials.

The Jakarta Persistence `IdentityProvider` creates a `SecurityIdentity` instance, which is used during user authentication to verify and authorize access requests making your Quarkus application secure.

For an example of practical use of Basic authentication and Jakarta Persistence, see the xref:security-basic-authentication-tutorial.adoc[Secure a Quarkus application with Basic authentication and Jakarta Persistence] tutorial.
For an example of practical use of Basic authentication and Jakarta Persistence, see the xref:security-getting-started-tutorial.adoc[Getting Started with Security using Basic authentication and Jakarta Persistence] tutorial.


== Jakarta Persistence entity specification

Check warning on line 21 in docs/src/main/asciidoc/security-jpa.adoc

View workflow job for this annotation

GitHub Actions / Linting with Vale

[vale] reported by reviewdog 🐶 [Quarkus.Headings] Use sentence-style capitalization in 'Jakarta Persistence entity specification'. Raw Output: {"message": "[Quarkus.Headings] Use sentence-style capitalization in 'Jakarta Persistence entity specification'.", "location": {"path": "docs/src/main/asciidoc/security-jpa.adoc", "range": {"start": {"line": 21, "column": 4}}}, "severity": "INFO"}

Quarkus security offers a Jakarta Persistence integration to collect usernames, passwords, and roles, and store them into Jakarta Persistence database entities.

Expand Down Expand Up @@ -111,35 +112,49 @@
public class Role extends PanacheEntity {

@ManyToMany(mappedBy = "roles")
public List<ExternalRolesUserEntity> users;
public List<User> users;

@RolesValue
public String role;
}
----

[NOTE]
====
The example shows how to store and access the roles, but if there's a need to update the existing user or create a new user. There will be a need to annotate `public List<Role> roles` with `@Cascade(CascadeType.ALL)` or select the specific type of `CascadeType`.

Check warning on line 124 in docs/src/main/asciidoc/security-jpa.adoc

View workflow job for this annotation

GitHub Actions / Linting with Vale

[vale] reported by reviewdog 🐶 [Quarkus.Fluff] Depending on the context, consider using 'Rewrite the sentence, or use 'must', instead of' rather than 'need to'. Raw Output: {"message": "[Quarkus.Fluff] Depending on the context, consider using 'Rewrite the sentence, or use 'must', instead of' rather than 'need to'.", "location": {"path": "docs/src/main/asciidoc/security-jpa.adoc", "range": {"start": {"line": 124, "column": 71}}}, "severity": "INFO"}

Check warning on line 124 in docs/src/main/asciidoc/security-jpa.adoc

View workflow job for this annotation

GitHub Actions / Linting with Vale

[vale] reported by reviewdog 🐶 [Quarkus.Fluff] Depending on the context, consider using 'Rewrite the sentence, or use 'must', instead of' rather than 'need to'. Raw Output: {"message": "[Quarkus.Fluff] Depending on the context, consider using 'Rewrite the sentence, or use 'must', instead of' rather than 'need to'.", "location": {"path": "docs/src/main/asciidoc/security-jpa.adoc", "range": {"start": {"line": 124, "column": 142}}}, "severity": "INFO"}
====

== Password storage and hashing

When developing applications with Quarkus, you can decide how to manage password storage and hashing. You can choose to keep the default password and hashing settings of Quarkus, or you can hash passwords manually.

With the default option, passwords are stored and hashed with https://en.wikipedia.org/wiki/Bcrypt[bcrypt] under the
https://en.wikipedia.org/wiki/Crypt_(C)[Modular Crypt Format] (MCF).
https://en.wikipedia.org/wiki/Crypt_\(C)[Modular Crypt Format] (MCF).
While using MCF, the hashing algorithm, iteration count, and salt are stored as a part of the hashed value.

Check warning on line 133 in docs/src/main/asciidoc/security-jpa.adoc

View workflow job for this annotation

GitHub Actions / Linting with Vale

[vale] reported by reviewdog 🐶 [Quarkus.TermsSuggestions] Depending on the context, consider using 'by using' or 'that uses' rather than 'using'. Raw Output: {"message": "[Quarkus.TermsSuggestions] Depending on the context, consider using 'by using' or 'that uses' rather than 'using'.", "location": {"path": "docs/src/main/asciidoc/security-jpa.adoc", "range": {"start": {"line": 133, "column": 6}}}, "severity": "INFO"}

Check warning on line 133 in docs/src/main/asciidoc/security-jpa.adoc

View workflow job for this annotation

GitHub Actions / Linting with Vale

[vale] reported by reviewdog 🐶 [Quarkus.TermsSuggestions] Depending on the context, consider using 'because' or 'while' rather than 'as'. Raw Output: {"message": "[Quarkus.TermsSuggestions] Depending on the context, consider using 'because' or 'while' rather than 'as'.", "location": {"path": "docs/src/main/asciidoc/security-jpa.adoc", "range": {"start": {"line": 133, "column": 78}}}, "severity": "INFO"}
As such, we do not need dedicated columns to keep them.

[NOTE]
====
In cryptography, a salt is a name for random data used as an additional input to a one-way function that hashes data, a password, or a passphrase.

Check warning on line 138 in docs/src/main/asciidoc/security-jpa.adoc

View workflow job for this annotation

GitHub Actions / Linting with Vale

[vale] reported by reviewdog 🐶 [Quarkus.TermsSuggestions] Depending on the context, consider using 'because' or 'while' rather than 'as'. Raw Output: {"message": "[Quarkus.TermsSuggestions] Depending on the context, consider using 'because' or 'while' rather than 'as'.", "location": {"path": "docs/src/main/asciidoc/security-jpa.adoc", "range": {"start": {"line": 138, "column": 56}}}, "severity": "INFO"}
====

To represent passwords stored in the database which were hashed using different hashing algorithms, create a class that implements `org.wildfly.security.password.PasswordProvider` as shown in the example below.
To represent passwords stored in the database which were hashed using different hashing algorithms, create a class that implements `io.quarkus.security.jpa.PasswordProvider` as shown in the example below.

Check warning on line 141 in docs/src/main/asciidoc/security-jpa.adoc

View workflow job for this annotation

GitHub Actions / Linting with Vale

[vale] reported by reviewdog 🐶 [Quarkus.TermsSuggestions] Depending on the context, consider using ', which (non restrictive clause preceded by a comma)' or 'that (restrictive clause without a comma)' rather than 'which'. Raw Output: {"message": "[Quarkus.TermsSuggestions] Depending on the context, consider using ', which (non restrictive clause preceded by a comma)' or 'that (restrictive clause without a comma)' rather than 'which'.", "location": {"path": "docs/src/main/asciidoc/security-jpa.adoc", "range": {"start": {"line": 141, "column": 46}}}, "severity": "INFO"}

Check warning on line 141 in docs/src/main/asciidoc/security-jpa.adoc

View workflow job for this annotation

GitHub Actions / Linting with Vale

[vale] reported by reviewdog 🐶 [Quarkus.TermsSuggestions] Depending on the context, consider using 'by using' or 'that uses' rather than 'using'. Raw Output: {"message": "[Quarkus.TermsSuggestions] Depending on the context, consider using 'by using' or 'that uses' rather than 'using'.", "location": {"path": "docs/src/main/asciidoc/security-jpa.adoc", "range": {"start": {"line": 141, "column": 64}}}, "severity": "INFO"}

The following snippet shows how to set a custom password provider that represents a password which was hashed with the SHA256 hashing algorithm.

Check warning on line 143 in docs/src/main/asciidoc/security-jpa.adoc

View workflow job for this annotation

GitHub Actions / Linting with Vale

[vale] reported by reviewdog 🐶 [Quarkus.TermsSuggestions] Depending on the context, consider using ', which (non restrictive clause preceded by a comma)' or 'that (restrictive clause without a comma)' rather than 'which'. Raw Output: {"message": "[Quarkus.TermsSuggestions] Depending on the context, consider using ', which (non restrictive clause preceded by a comma)' or 'that (restrictive clause without a comma)' rather than 'which'.", "location": {"path": "docs/src/main/asciidoc/security-jpa.adoc", "range": {"start": {"line": 143, "column": 93}}}, "severity": "INFO"}

[source,java]
----
import org.wildfly.security.password.Password;
import org.wildfly.security.password.PasswordProvider;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import jakarta.persistence.Table;

import io.quarkus.security.jpa.Password;
import io.quarkus.security.jpa.PasswordType;
import io.quarkus.security.jpa.Roles;
import io.quarkus.security.jpa.UserDefinition;
import io.quarkus.security.jpa.Username;

@UserDefinition
@Table(name = "test_user")
Expand All @@ -160,6 +175,16 @@
@Roles
public String role;
}
----

[source,java]
----
import jakarta.xml.bind.DatatypeConverter;

import org.wildfly.security.password.Password;
import org.wildfly.security.password.interfaces.SimpleDigestPassword;

import io.quarkus.security.jpa.PasswordProvider;

public class CustomPasswordProvider implements PasswordProvider {
@Override
Expand Down
Loading