-
Notifications
You must be signed in to change notification settings - Fork 4
Add JwtEncoderAlternative #30
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
base: jwt-encoder
Are you sure you want to change the base?
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,61 @@ | ||
| /* | ||
| * Copyright 2002-2021 the original author or authors. | ||
| * | ||
| * 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 | ||
| * | ||
| * https://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. | ||
| */ | ||
|
|
||
| package org.springframework.security.oauth2.jwt; | ||
|
|
||
| import java.util.Map; | ||
| import java.util.function.Consumer; | ||
|
|
||
| import org.springframework.security.oauth2.jose.jws.JwsAlgorithm; | ||
|
|
||
| public interface JwsHeaderMutator<M extends JwsHeaderMutator<M>> { | ||
| /** | ||
| * Set the algorithm {@code (alg)} header which identifies the algorithm | ||
| * used when signing the JWS | ||
| * | ||
| * @return the {@link JwsHeaderMutator} for more customizations | ||
| */ | ||
| default M algorithm(JwsAlgorithm jws) { | ||
| return header(JoseHeaderNames.ALG, jws); | ||
| } | ||
|
|
||
| /** | ||
| * Set a header that is critical for decoders to understand | ||
| * | ||
| * @param name the header name | ||
| * @param value the header value | ||
| * @return the {@link JwsHeaderMutator} for more customizations | ||
| */ | ||
| default M criticalHeader(String name, Object value) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The JWS spec indicates that when the Critical headers are still added, but they also ultimately add the |
||
| return criticalHeaders((crit) -> crit.put(name, value)); | ||
| } | ||
|
|
||
| M criticalHeaders(Consumer<Map<String, Object>> criticalHeadersConsumer); | ||
|
|
||
| /** | ||
| * Set a header | ||
| * | ||
| * Note that key-specific headers are typically best specified by the encoder | ||
| * itself. | ||
| * | ||
| * See {@link JwtEncoderAlternative} | ||
| */ | ||
| default M header(String name, Object value) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since no other headers are required, and since those headers are quite easy to get wrong in the general case, I think it's best to leave other headers out for now. Generally speaking, those headers are for looking up keys anyway, which is something likely better decided centrally in an encoder instead of by the caller. And even if that's not the case, this method still exists so that an application can specify them if needed. |
||
| return headers((headers) -> headers.put(name, value)); | ||
| } | ||
|
|
||
| M headers(Consumer<Map<String, Object>> headersConsumer); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,108 @@ | ||
| /* | ||
| * Copyright 2002-2021 the original author or authors. | ||
| * | ||
| * 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 | ||
| * | ||
| * https://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. | ||
| */ | ||
|
|
||
| package org.springframework.security.oauth2.jwt; | ||
|
|
||
| import java.time.Instant; | ||
| import java.util.List; | ||
| import java.util.Map; | ||
| import java.util.function.Consumer; | ||
|
|
||
| /** | ||
| * A claims mutator for the "claims" that may be contained in the JSON | ||
| * object JWT Claims Set of a JSON Web Token (JWT). | ||
| * | ||
| * @author Josh Cummings | ||
| * @since 5.5 | ||
| * @see JwtClaimNames | ||
| * @see Jwt | ||
| * @see <a target="_blank" href= | ||
| * "https://tools.ietf.org/html/rfc7519#section-4.1">Registered Claim Names</a> | ||
| */ | ||
| public interface JwtClaimMutator<M extends JwtClaimMutator<M>> { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I like the symmetry that this provides to |
||
|
|
||
| /** | ||
| * Returns the Issuer {@code (iss)} claim which identifies the principal that issued | ||
| * the JWT. | ||
| * @return the Issuer identifier | ||
| */ | ||
| default M issuer(String uri) { | ||
| return claim(JwtClaimNames.ISS, uri); | ||
| } | ||
|
|
||
| /** | ||
| * Returns the Subject {@code (sub)} claim which identifies the principal that is the | ||
| * subject of the JWT. | ||
| * @return the Subject identifier | ||
| */ | ||
| default M subject(String sub) { | ||
| return claim(JwtClaimNames.SUB, sub); | ||
| } | ||
|
|
||
| /** | ||
| * Returns the Audience {@code (aud)} claim which identifies the recipient(s) that the | ||
| * JWT is intended for. | ||
| * @return the Audience(s) that this JWT intended for | ||
| */ | ||
| default M audience(List<String> audience) { | ||
| return claim(JwtClaimNames.AUD, audience); | ||
| } | ||
|
|
||
| /** | ||
| * Returns the Expiration time {@code (exp)} claim which identifies the expiration | ||
| * time on or after which the JWT MUST NOT be accepted for processing. | ||
| * @return the Expiration time on or after which the JWT MUST NOT be accepted for | ||
| * processing | ||
| */ | ||
| default M expiresAt(Instant expiresAt) { | ||
| return claim(JwtClaimNames.EXP, expiresAt); | ||
| } | ||
|
|
||
| /** | ||
| * Returns the Not Before {@code (nbf)} claim which identifies the time before which | ||
| * the JWT MUST NOT be accepted for processing. | ||
| * @return the Not Before time before which the JWT MUST NOT be accepted for | ||
| * processing | ||
| */ | ||
| default M notBefore(Instant notBefore) { | ||
| return claim(JwtClaimNames.NBF, notBefore); | ||
| } | ||
|
|
||
| /** | ||
| * Returns the Issued at {@code (iat)} claim which identifies the time at which the | ||
| * JWT was issued. | ||
| * @return the Issued at claim which identifies the time at which the JWT was issued | ||
| */ | ||
| default M issuedAt(Instant issuedAt) { | ||
| return claim(JwtClaimNames.IAT, issuedAt); | ||
| } | ||
|
|
||
| /** | ||
| * Sets the JWT ID {@code (jti)} claim which provides a unique identifier for the | ||
| * JWT. | ||
| * @return the {@link JwtClaimMutator} for more customizations | ||
| */ | ||
| default M id(String id) { | ||
| return claim(JwtClaimNames.JTI, id); | ||
| } | ||
|
|
||
| default M claim(String name, Object value) { | ||
| claims((claims) -> claims.put(name, value)); | ||
| return (M) this; | ||
| } | ||
|
|
||
| M claims(Consumer<Map<String, Object>> claimsConsumer); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,60 @@ | ||
| /* | ||
| * Copyright 2002-2021 the original author or authors. | ||
| * | ||
| * 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 | ||
| * | ||
| * https://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. | ||
| */ | ||
|
|
||
| package org.springframework.security.oauth2.jwt; | ||
|
|
||
| import java.util.function.Consumer; | ||
|
|
||
| /** | ||
| * Encodes and signs JWTs, implementations may also support encryption. | ||
| */ | ||
| public interface JwtEncoderAlternative { | ||
|
|
||
| /** | ||
| * Return a {@link JwtMutator} for specifying any claims or headers needed in the JWT | ||
| * | ||
| * @return a parameter mutator | ||
| */ | ||
| JwtMutator<?> encoder(); | ||
|
|
||
| /** | ||
| * A parameter mutator for specifying headers and claims to encode | ||
| */ | ||
| interface JwtMutator<B extends JwtMutator<B>> { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's more natural to return a builder-like object since encoding a JWT is a sophisticated operation with a hard-to-reverse result. |
||
| /** | ||
| * Mutate the JWS headers | ||
| * | ||
| * @param headersConsumer the {@link Consumer} that mutates the JWS headers | ||
| * @return the {@link JwtMutator} for further customizations | ||
| */ | ||
| B jwsHeaders(Consumer<JwsHeaderMutator<?>> headersConsumer); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. By expressing these as optional method parameters, it allows the API to add more parameters in the future. For example, JWE support could be added by adding a This kind of separation also allows for clarity when the caller wants to indicate the JWS algorithm and the JWE algorithm. |
||
|
|
||
| /** | ||
| * Mutate the JWT Claims Set | ||
| * | ||
| * @param claimsConsumer the {@link Consumer} that mutates the JWT Claims Set | ||
| * @return the {@link JwtMutator} for further customizations | ||
| */ | ||
| B claims(Consumer<JwtClaimMutator<?>> claimsConsumer); | ||
|
|
||
| /** | ||
| * Sign and serialize the JWT | ||
| * | ||
| * @return the signed and serialized JWT | ||
| */ | ||
| String encode(); | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This interface represents the minimal set of headers necessary to specify a JWT.
I like this interface due to the symmetry it provides to Spring Security's claim accessors, like
JwtClaimAccessor.