11/**
22 * Copyright 2020 Dhatim
3- *
3+ * <p>
44 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
55 * use this file except in compliance with the License. You may obtain a copy of
66 * the License at
7- *
7+ * <p>
88 * http://www.apache.org/licenses/LICENSE-2.0
9- *
9+ * <p>
1010 * Unless required by applicable law or agreed to in writing, software
1111 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
1212 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
3030import io .jsonwebtoken .Claims ;
3131import io .jsonwebtoken .SignatureAlgorithm ;
3232import io .jsonwebtoken .impl .DefaultClaims ;
33+ import org .glassfish .jersey .server .filter .RolesAllowedDynamicFeature ;
34+
35+ import javax .crypto .KeyGenerator ;
36+ import javax .crypto .spec .SecretKeySpec ;
37+ import javax .ws .rs .container .ContainerResponseFilter ;
3338import java .nio .charset .StandardCharsets ;
3439import java .security .Key ;
3540import java .security .NoSuchAlgorithmException ;
3641import java .time .Duration ;
3742import java .util .Optional ;
3843import java .util .function .BiFunction ;
3944import java .util .function .Function ;
40- import javax .crypto .KeyGenerator ;
41- import javax .crypto .spec .SecretKeySpec ;
42- import javax .ws .rs .container .ContainerResponseFilter ;
43- import org .glassfish .jersey .server .filter .RolesAllowedDynamicFeature ;
4445
4546/**
4647 * Dopwizard bundle
48+ *
4749 * @param <C> Your application configuration class
4850 * @param <P> the class of the principal that will be serialized in / deserialized from JWT cookies
4951 */
50- public class JwtCookieAuthBundle <C extends Configuration , P extends JwtCookiePrincipal > implements ConfiguredBundle <C >{
52+ public class JwtCookieAuthBundle <C extends Configuration , P extends JwtCookiePrincipal > implements ConfiguredBundle <C > {
5153
54+ public static final String JWT_COOKIE_DEFAULT_NAME = "sessionToken" ;
5255 private static final String JWT_COOKIE_PREFIX = "jwtCookie" ;
53- private static final String DEFAULT_COOKIE_NAME = "sessionToken" ;
5456
5557 private final Class <P > principalType ;
56- private final Function <P ,Claims > serializer ;
58+ private final Function <P , Claims > serializer ;
5759 private final Function <Claims , P > deserializer ;
5860 private Function <C , JwtCookieAuthConfiguration > configurationSupplier ;
5961 private BiFunction <C , Environment , Key > keySuppplier ;
6062
6163 /**
6264 * Get a bundle instance that will use DefaultJwtCookiePrincipal
65+ *
6366 * @param <C> Your application configuration class
6467 * @return a bundle instance that will use DefaultJwtCookiePrincipal
6568 */
66- public static <C extends Configuration > JwtCookieAuthBundle <C , DefaultJwtCookiePrincipal > getDefault (){
69+ public static <C extends Configuration > JwtCookieAuthBundle <C , DefaultJwtCookiePrincipal > getDefault () {
6770 return new JwtCookieAuthBundle <>(
6871 DefaultJwtCookiePrincipal .class ,
6972 DefaultJwtCookiePrincipal ::getClaims ,
@@ -72,11 +75,12 @@ public static <C extends Configuration> JwtCookieAuthBundle<C, DefaultJwtCookieP
7275
7376 /**
7477 * Build a new instance of JwtCookieAuthBundle
78+ *
7579 * @param principalType the class of the principal that will be serialized in / deserialized from JWT cookies
76- * @param serializer a function to serialize principals into JWT claims
77- * @param deserializer a function to deserialize JWT claims into principals
80+ * @param serializer a function to serialize principals into JWT claims
81+ * @param deserializer a function to deserialize JWT claims into principals
7882 */
79- public JwtCookieAuthBundle (Class <P > principalType , Function <P ,Claims > serializer , Function <Claims , P > deserializer ) {
83+ public JwtCookieAuthBundle (Class <P > principalType , Function <P , Claims > serializer , Function <Claims , P > deserializer ) {
8084 this .principalType = principalType ;
8185 this .serializer = serializer ;
8286 this .deserializer = deserializer ;
@@ -85,16 +89,18 @@ public JwtCookieAuthBundle(Class<P> principalType, Function<P,Claims> serializer
8589
8690 /**
8791 * If you want to sign the JWT with your own key, specify it here
92+ *
8893 * @param keySupplier a bi-function which will return the signing key from the configuration and environment
8994 * @return this
9095 */
91- public JwtCookieAuthBundle <C , P > withKeyProvider (BiFunction <C , Environment , Key > keySupplier ){
96+ public JwtCookieAuthBundle <C , P > withKeyProvider (BiFunction <C , Environment , Key > keySupplier ) {
9297 this .keySuppplier = keySupplier ;
9398 return this ;
9499 }
95100
96101 /**
97102 * If you need to configure the bundle, specify it here
103+ *
98104 * @param configurationSupplier a bi-function which will return the bundle configuration from the application configuration
99105 * @return this
100106 */
@@ -121,38 +127,52 @@ public void run(C configuration, Environment environment) throws Exception {
121127 .orElseGet (() -> generateKey (conf .getSecretSeed ()));
122128
123129 JerseyEnvironment jerseyEnvironment = environment .jersey ();
124- jerseyEnvironment .register (new AuthDynamicFeature (getAuthRequestFilter (key )));
130+ jerseyEnvironment .register (new AuthDynamicFeature (getAuthRequestFilter (key , conf . getCookieName () )));
125131 jerseyEnvironment .register (new AuthValueFactoryProvider .Binder <>(principalType ));
126132 jerseyEnvironment .register (RolesAllowedDynamicFeature .class );
127133 jerseyEnvironment .register (getAuthResponseFilter (key , conf ));
128134 jerseyEnvironment .register (DontRefreshSessionFilter .class );
129135 }
130136
131137 /**
132- * Get a filter that will desezialize the principal from JWT cookies found in HTTP requests
133- * @param key the key used to validate the JWT
138+ * Get a filter that will deserialize the principal from JWT cookies found in HTTP requests
139+ *
140+ * @param key the key used to validate the JWT
141+ * @param cookieName the name of the cookie holding the JWT
134142 * @return the request filter
135143 */
136- public AuthFilter <String , P > getAuthRequestFilter (Key key ) {
144+ public AuthFilter <String , P > getAuthRequestFilter (Key key , String cookieName ) {
137145 return new JwtCookieAuthRequestFilter .Builder ()
138- .setCookieName (DEFAULT_COOKIE_NAME )
146+ .setCookieName (cookieName )
139147 .setAuthenticator (new JwtCookiePrincipalAuthenticator (key , deserializer ))
140148 .setPrefix (JWT_COOKIE_PREFIX )
141- .setAuthorizer ((Authorizer <P >)(P ::isInRole ))
149+ .setAuthorizer ((Authorizer <P >) (P ::isInRole ))
142150 .buildAuthFilter ();
143151 }
144152
153+ /**
154+ * Get a filter that will deserialize the principal from JWT cookies found in HTTP requests,
155+ * using the default cookie name.
156+ *
157+ * @param key the key used to validate the JWT
158+ * @return the request filter
159+ */
160+ public AuthFilter <String , P > getAuthRequestFilter (Key key ) {
161+ return getAuthRequestFilter (key , JWT_COOKIE_DEFAULT_NAME );
162+ }
163+
145164 /**
146165 * Get a filter that will serialize principals into JWTs and add them to HTTP response cookies
147- * @param key the key used to sign the JWT
166+ *
167+ * @param key the key used to sign the JWT
148168 * @param configuration cookie configuration (secure, httpOnly, expiration...)
149169 * @return the response filter
150170 */
151171 public ContainerResponseFilter getAuthResponseFilter (Key key , JwtCookieAuthConfiguration configuration ) {
152172 return new JwtCookieAuthResponseFilter <>(
153173 principalType ,
154174 serializer ,
155- DEFAULT_COOKIE_NAME ,
175+ configuration . getCookieName () ,
156176 configuration .isSecure (),
157177 configuration .isHttpOnly (),
158178 configuration .getDomain (),
@@ -164,9 +184,10 @@ public ContainerResponseFilter getAuthResponseFilter(Key key, JwtCookieAuthConfi
164184
165185 /**
166186 * Generate a HMAC SHA256 Key that can be used to sign JWTs
187+ *
167188 * @param secretSeed a seed from which the key will be generated.
168- * Identical seeds will generate identical keys.
169- * If null, a random key is returned.
189+ * Identical seeds will generate identical keys.
190+ * If null, a random key is returned.
170191 * @return a HMAC SHA256 Key
171192 */
172193 public static Key generateKey (String secretSeed ) {
@@ -178,10 +199,10 @@ public static Key generateKey(String secretSeed) {
178199 .orElseGet (getHmacSha256KeyGenerator ()::generateKey );
179200 }
180201
181- private static KeyGenerator getHmacSha256KeyGenerator (){
182- try {
202+ private static KeyGenerator getHmacSha256KeyGenerator () {
203+ try {
183204 return KeyGenerator .getInstance (SignatureAlgorithm .HS256 .getJcaName ());
184- } catch (NoSuchAlgorithmException e ){
205+ } catch (NoSuchAlgorithmException e ) {
185206 throw new SecurityException (e );
186207 }
187208 }
0 commit comments