1515import javax .ws .rs .Priorities ;
1616import javax .ws .rs .WebApplicationException ;
1717import javax .ws .rs .container .ContainerRequestContext ;
18+ import javax .ws .rs .core .Cookie ;
1819import javax .ws .rs .core .HttpHeaders ;
20+ import javax .ws .rs .core .MultivaluedMap ;
1921import javax .ws .rs .core .SecurityContext ;
2022import java .io .IOException ;
2123import java .security .Principal ;
24+ import java .util .Map ;
2225
2326@ Priority (Priorities .AUTHENTICATION )
2427public class JWTAuthFilter <P extends Principal > extends AuthFilter <JsonWebToken , P > {
@@ -27,62 +30,114 @@ public class JWTAuthFilter<P extends Principal> extends AuthFilter<JsonWebToken,
2730
2831 private final JsonWebTokenVerifier tokenVerifier ;
2932 private final JsonWebTokenParser tokenParser ;
33+ private final String cookieName ;
3034
31- private JWTAuthFilter (JsonWebTokenParser tokenParser , JsonWebTokenVerifier tokenVerifier ) {
35+ private JWTAuthFilter (JsonWebTokenParser tokenParser , JsonWebTokenVerifier tokenVerifier , String cookieName ) {
3236 this .tokenParser = tokenParser ;
3337 this .tokenVerifier = tokenVerifier ;
38+ this .cookieName = cookieName ;
3439 }
3540
3641 @ Override
3742 public void filter (final ContainerRequestContext requestContext ) throws IOException {
38- final String header = requestContext .getHeaders ().getFirst (HttpHeaders .AUTHORIZATION );
43+ Optional <String > optionalToken = getTokenFromCookieOrHeader (requestContext );
44+
45+ if (optionalToken .isPresent ()) {
46+ try {
47+ final JsonWebToken token = verifiedToken (optionalToken );
48+ final Optional <P > principal = authenticator .authenticate (token );
49+
50+ if (principal .isPresent ()) {
51+ requestContext .setSecurityContext (new SecurityContext () {
52+
53+ @ Override
54+ public Principal getUserPrincipal () {
55+ return principal .get ();
56+ }
57+
58+ @ Override
59+ public boolean isUserInRole (String role ) {
60+ return authorizer .authorize (principal .get (), role );
61+ }
62+
63+ @ Override
64+ public boolean isSecure () {
65+ return requestContext .getSecurityContext ().isSecure ();
66+ }
67+
68+ @ Override
69+ public String getAuthenticationScheme () {
70+ return SecurityContext .BASIC_AUTH ;
71+ }
72+
73+ });
74+ return ;
75+ }
76+ }
77+ catch (JsonWebTokenException ex ) {
78+ LOGGER .warn ("Error decoding credentials: " + ex .getMessage (), ex );
79+ }
80+ catch (AuthenticationException ex ) {
81+ LOGGER .warn ("Error authenticating credentials" , ex );
82+ throw new InternalServerErrorException ();
83+ }
84+ }
85+
86+ throw new WebApplicationException (unauthorizedHandler .buildResponse (prefix , realm ));
87+ }
88+
89+ private JsonWebToken verifiedToken (Optional <String > optionalToken ) {
90+ final String rawToken = optionalToken .get ();
91+ final JsonWebToken token = tokenParser .parse (rawToken );
92+ tokenVerifier .verifySignature (token );
93+ return token ;
94+ }
95+
96+ public Optional <String > getTokenFromCookieOrHeader (ContainerRequestContext requestContext ) {
97+ Optional <String > headerToken = getTokenFromHeader (requestContext .getHeaders ());
98+
99+ if (headerToken .isPresent ()) {
100+ return headerToken ;
101+ }
102+ else {
103+ Optional <String > cookieToken = getTokenFromCookie (requestContext );
104+
105+ if (cookieToken .isPresent ()) {
106+ return cookieToken ;
107+ }
108+ else {
109+ return Optional .absent ();
110+ }
111+ }
112+ }
113+
114+ private Optional <String > getTokenFromHeader (MultivaluedMap <String , String > headers ) {
115+ String header = headers .getFirst (HttpHeaders .AUTHORIZATION );
39116 if (header != null ) {
40- final int space = header .indexOf (' ' );
117+ int space = header .indexOf (' ' );
41118 if (space > 0 ) {
42- final String method = header .substring (0 , space );
119+ String method = header .substring (0 , space );
43120 if (prefix .equalsIgnoreCase (method )) {
44- try {
45- final String rawToken = header .substring (space + 1 );
46- final JsonWebToken token = tokenParser .parse (rawToken );
47-
48- tokenVerifier .verifySignature (token );
49-
50- final Optional <P > principal = authenticator .authenticate (token );
51- if (principal .isPresent ()) {
52- requestContext .setSecurityContext (new SecurityContext () {
53- @ Override
54- public Principal getUserPrincipal () {
55- return principal .get ();
56- }
57-
58- @ Override
59- public boolean isUserInRole (String role ) {
60- return authorizer .authorize (principal .get (), role );
61- }
62-
63- @ Override
64- public boolean isSecure () {
65- return requestContext .getSecurityContext ().isSecure ();
66- }
67-
68- @ Override
69- public String getAuthenticationScheme () {
70- return SecurityContext .BASIC_AUTH ;
71- }
72- });
73- return ;
74- }
75- } catch (JsonWebTokenException e ) {
76- LOGGER .warn ("Error decoding credentials: " + e .getMessage (), e );
77- } catch (AuthenticationException e ) {
78- LOGGER .warn ("Error authenticating credentials" , e );
79- throw new InternalServerErrorException ();
80- }
121+ String rawToken = header .substring (space + 1 );
122+ return Optional .of (rawToken );
81123 }
82124 }
83125 }
84126
85- throw new WebApplicationException (unauthorizedHandler .buildResponse (prefix , realm ));
127+ return Optional .absent ();
128+ }
129+
130+ public Optional <String > getTokenFromCookie (ContainerRequestContext requestContext ) {
131+ Map <String , Cookie > cookies = requestContext .getCookies ();
132+
133+ if (cookieName != null && cookies .containsKey (cookieName )) {
134+ Cookie tokenCookie = cookies .get (cookieName );
135+ String rawToken = tokenCookie .getValue ();
136+
137+ return Optional .of (rawToken );
138+ }
139+
140+ return Optional .absent ();
86141 }
87142
88143 /**
@@ -95,6 +150,7 @@ public static class Builder<P extends Principal> extends AuthFilterBuilder<JsonW
95150
96151 private JsonWebTokenParser parser ;
97152 private JsonWebTokenVerifier verifier ;
153+ private String cookieName ;
98154
99155 public Builder <P > setTokenParser (JsonWebTokenParser parser ) {
100156 this .parser = parser ;
@@ -106,11 +162,17 @@ public Builder<P> setTokenVerifier(JsonWebTokenVerifier verifier) {
106162 return this ;
107163 }
108164
165+ public Builder <P > setCookieName (String cookieName ) {
166+ this .cookieName = cookieName ;
167+ return this ;
168+ }
169+
109170 @ Override
110171 protected JWTAuthFilter <P > newInstance () {
111172 Preconditions .checkArgument (parser != null , "JsonWebTokenParser is not set" );
112173 Preconditions .checkArgument (verifier != null , "JsonWebTokenVerifier is not set" );
113- return new JWTAuthFilter <>(parser , verifier );
174+ return new JWTAuthFilter <>(parser , verifier , cookieName );
114175 }
115176 }
177+
116178}
0 commit comments