Skip to content

Commit

Permalink
Docs: Security JWT guide minor fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
michalvavrik committed Dec 14, 2023
1 parent 4f2ac71 commit fa8a3cf
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 27 deletions.
2 changes: 1 addition & 1 deletion docs/src/main/asciidoc/security-jwt-build.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ SmallRye JWT supports the following properties which can be used to customize th
|===
|Property Name|Default|Description
|smallrye.jwt.sign.key.location|`none`|Location of a private key which will be used to sign the claims when either a no-argument `sign()` or `innerSign()` method is called.

Check warning on line 320 in docs/src/main/asciidoc/security-jwt-build.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-jwt-build.adoc", "range": {"start": {"line": 320, "column": 54}}}, "severity": "INFO"}
|smallrye.jwt.sign.key|none|Key value which will be used to sign the claims when either a no-argument sign() or innerSign() method is called.
|smallrye.jwt.sign.key|none|Key value which will be used to sign the claims when either a no-argument `sign()` or `innerSign()` method is called.

Check warning on line 321 in docs/src/main/asciidoc/security-jwt-build.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-jwt-build.adoc", "range": {"start": {"line": 321, "column": 27}}}, "severity": "INFO"}
|smallrye.jwt.sign.key.id|`none`|Signing key identifier which is checked only when JWK keys are used.

Check warning on line 322 in docs/src/main/asciidoc/security-jwt-build.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-jwt-build.adoc", "range": {"start": {"line": 322, "column": 45}}}, "severity": "INFO"}
|smallrye.jwt.encrypt.key.location|`none`|Location of a public key which will be used to encrypt the claims or inner JWT when a no-argument `encrypt()` method is called.

Check warning on line 323 in docs/src/main/asciidoc/security-jwt-build.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-jwt-build.adoc", "range": {"start": {"line": 323, "column": 56}}}, "severity": "INFO"}
|smallrye.jwt.sign.relax-key-validation|false|Relax the validation of the signing keys.
Expand Down
58 changes: 32 additions & 26 deletions docs/src/main/asciidoc/security-jwt.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -134,9 +134,9 @@ public class TokenSecuredResource {
}
}
----
<1> Here we inject the JsonWebToken interface, an extension of the java.security.
Principal interface that provides access to the claims associated with the current authenticated token.
<2> @PermitAll is a JSR 250 common security annotation that indicates that the given endpoint is accessible by any caller, authenticated or not.
<1> Here we inject the JsonWebToken interface, an extension of the java.security.Principal

Check failure on line 137 in docs/src/main/asciidoc/security-jwt.adoc

View workflow job for this annotation

GitHub Actions / Linting with Vale

[vale] reported by reviewdog 🐶 [Quarkus.Spacing] Keep one space between words in 'y.P'. Raw Output: {"message": "[Quarkus.Spacing] Keep one space between words in 'y.P'.", "location": {"path": "docs/src/main/asciidoc/security-jwt.adoc", "range": {"start": {"line": 137, "column": 69}}}, "severity": "ERROR"}
interface that provides access to the claims associated with the current authenticated token.
<2> @PermitAll is a Jakarta common security annotation that indicates that the given endpoint is accessible by any caller, authenticated or not.
<3> Here we inject the Jakarta REST SecurityContext to inspect the security state of the call and use a `getResponseString()` function to populate a response string.
<4> Here we check if the call is insecure by checking the request user/caller `Principal` against null.
<5> Here we check that the Principal and JsonWebToken have the same name since JsonWebToken does represent the current Principal.
Expand Down Expand Up @@ -252,7 +252,7 @@ public class TokenSecuredResource {
----
<1> Here we inject `JsonWebToken`
<2> This new endpoint will be located at /secured/roles-allowed
<3> @RolesAllowed is a JSR 250 common security annotation that indicates that the given endpoint is accessible by a caller if
<3> @RolesAllowed is a Jakarta common security annotation that indicates that the given endpoint is accessible by a caller if
they have either a "User" or "Admin" role assigned.
<4> Here we build the reply the same way as in the `hello` method but also add a value of the JWT `birthdate` claim by directly calling the injected `JsonWebToken`.

Check warning on line 257 in docs/src/main/asciidoc/security-jwt.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-jwt.adoc", "range": {"start": {"line": 257, "column": 31}}}, "severity": "INFO"}

Expand All @@ -279,7 +279,6 @@ $ curl -v http://127.0.0.1:8080/secured/roles-allowed; echo
< Date: Sun, 03 Mar 2019 16:32:34 GMT
<
* Connection #0 to host 127.0.0.1 left intact
Not authorized
----

Excellent, we have not provided any JWT in the request, so we should not be able to access the endpoint, and we were not. Instead, we received an HTTP 401 Unauthorized error.

Check warning on line 284 in docs/src/main/asciidoc/security-jwt.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-jwt.adoc", "range": {"start": {"line": 284, "column": 168}}}, "severity": "INFO"}
Expand All @@ -297,7 +296,7 @@ mp.jwt.verify.issuer=https://example.com/issuer #<2>
quarkus.native.resources.includes=publicKey.pem #<3>
----
<1> We are setting public key location to point to a classpath publicKey.pem location. We will add this key in part B, <<add-public-key>>.
<1> We are setting public key location to point to a classpath `publicKey.pem` location. We will add this key in part B, <<add-public-key>>.
<2> We are setting the issuer to the URL string `https://example.com/issuer`.
<3> We are including the public key as a resource in the native executable.

Check warning on line 301 in docs/src/main/asciidoc/security-jwt.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-jwt.adoc", "range": {"start": {"line": 301, "column": 26}}}, "severity": "INFO"}

Expand Down Expand Up @@ -711,8 +710,14 @@ You can also use it to customize the way the token is verified or decrypted. For

[source,java]
----
import javax.crypto.SecretKey;
package org.acme.security.jwt;
import io.smallrye.jwt.auth.principal.ParseException;
import jakarta.inject.Inject;
import jakarta.ws.rs.CookieParam;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.NewCookie;
import jakarta.ws.rs.core.Response;
import org.eclipse.microprofile.jwt.JsonWebToken;
Expand All @@ -721,26 +726,27 @@ import io.smallrye.jwt.build.Jwt;
@Path("/secured")
public class SecuredResource {
@Inject JWTParser parser;
private String secret = "AyM1SysPpbyDfgZld3umj1qzKObwVMko";
@GET
@Produces("text/plain")
public Response getUserName(@CookieParam("jwt") String jwtCookie) {
Response response = null;
if (jwtCookie == null) {
// Create a JWT token signed using the 'HS256' algorithm
String newJwtCookie = Jwt.upn("Alice").signWithSecret(secret);
// or create a JWT token encrypted using the 'A256KW' algorithm
// Jwt.upn("alice").encryptWithSecret(secret);
return Response.ok("Alice").cookie(new NewCookie("jwt", newJwtCookie)).build();
} else {
// All mp.jwt and smallrye.jwt properties are still effective, only the verification key is customized.
JsonWebToken jwt = parser.verify(jwtCookie, secret);
// or jwt = parser.decrypt(jwtCookie, secret);
return Response.ok(jwt.getName()).build();
private static final String SECRET = "AyM1SysPpbyDfgZld3umj1qzKObwVMko";
@Inject
JWTParser parser;
@GET
@Produces("text/plain")
public Response getUserName(@CookieParam("jwt") String jwtCookie) throws ParseException {
if (jwtCookie == null) {
// Create a JWT token signed using the 'HS256' algorithm
String newJwtCookie = Jwt.upn("Alice").signWithSecret(SECRET);
// or create a JWT token encrypted using the 'A256KW' algorithm
// Jwt.upn("alice").encryptWithSecret(secret);
return Response.ok("Alice").cookie(new NewCookie("jwt", newJwtCookie)).build();
} else {
// All mp.jwt and smallrye.jwt properties are still effective, only the verification key is customized.
JsonWebToken jwt = parser.verify(jwtCookie, SECRET);
// or jwt = parser.decrypt(jwtCookie, secret);
return Response.ok(jwt.getName()).build();
}
}
}
}
----

Expand Down

0 comments on commit fa8a3cf

Please sign in to comment.