Skip to content

Commit b8c9532

Browse files
U-MITRE\mjwalshU-MITRE\mjwalsh
authored andcommitted
integration changes to client
1 parent 1a1ae4c commit b8c9532

File tree

3 files changed

+149
-48
lines changed

3 files changed

+149
-48
lines changed

openid-connect-client/src/main/java/org/mitre/openid/connect/client/OpenIdConnectAuthenticationFilter.java

Lines changed: 80 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@
1010
import java.security.PrivateKey;
1111
import java.security.PublicKey;
1212
import java.security.Signature;
13+
import java.util.Arrays;
1314
import java.util.Enumeration;
1415
import java.util.HashMap;
16+
import java.util.List;
1517
import java.util.Map;
1618
import java.util.Random;
1719

@@ -21,14 +23,13 @@
2123
import javax.servlet.http.HttpServletResponse;
2224

2325
import org.apache.commons.codec.binary.Base64;
24-
import org.apache.commons.logging.Log;
25-
import org.apache.commons.logging.LogFactory;
2626
import org.apache.http.auth.AuthScope;
2727
import org.apache.http.auth.UsernamePasswordCredentials;
2828
import org.apache.http.client.HttpClient;
2929
import org.apache.http.impl.client.DefaultHttpClient;
3030
import org.mitre.openid.connect.model.IdToken;
3131
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
32+
import org.springframework.security.authentication.AuthenticationServiceException;
3233
import org.springframework.security.core.Authentication;
3334
import org.springframework.security.core.AuthenticationException;
3435
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
@@ -85,9 +86,6 @@
8586
public class OpenIdConnectAuthenticationFilter extends
8687
AbstractAuthenticationProcessingFilter {
8788

88-
private static Log logger = LogFactory
89-
.getLog(OpenIdConnectAuthenticationFilter.class);
90-
9189
private final static int HTTP_SOCKET_TIMEOUT = 30000;
9290
private final static String SCOPE = "openid";
9391
private final static int KEY_SIZE = 1024;
@@ -259,9 +257,18 @@ public void afterPropertiesSet() {
259257
}
260258

261259
// prepend the spec necessary scope
262-
setScope(SCOPE + ((scope != null && !scope.isEmpty()) ? " " + scope : ""));
260+
setScope((scope != null && !scope.isEmpty()) ? SCOPE + " " + scope
261+
: SCOPE);
263262
}
264263

264+
/*
265+
* (non-Javadoc)
266+
*
267+
* @see org.springframework.security.web.authentication.
268+
* AbstractAuthenticationProcessingFilter
269+
* #attemptAuthentication(javax.servlet.http.HttpServletRequest,
270+
* javax.servlet.http.HttpServletResponse)
271+
*/
265272
/*
266273
* (non-Javadoc)
267274
*
@@ -275,6 +282,8 @@ public Authentication attemptAuthentication(HttpServletRequest request,
275282
HttpServletResponse response) throws AuthenticationException,
276283
IOException, ServletException {
277284

285+
final boolean debug = logger.isDebugEnabled();
286+
278287
if (request.getParameter("error") != null) {
279288

280289
// Handle Authorization Endpoint error
@@ -313,10 +322,12 @@ public Authentication attemptAuthentication(HttpServletRequest request,
313322
httpClient.getParams().setParameter("http.socket.timeout",
314323
new Integer(httpSocketTimeout));
315324

316-
UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(
317-
clientId, clientSecret);
318-
((DefaultHttpClient) httpClient).getCredentialsProvider()
319-
.setCredentials(AuthScope.ANY, credentials);
325+
//
326+
// TODO: basic auth is untested (it wasn't working last I tested)
327+
// UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(
328+
// clientId, clientSecret);
329+
// ((DefaultHttpClient) httpClient).getCredentialsProvider()
330+
// .setCredentials(AuthScope.ANY, credentials);
320331

321332
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(
322333
httpClient);
@@ -326,7 +337,18 @@ public Authentication attemptAuthentication(HttpServletRequest request,
326337
MultiValueMap<String, String> form = new LinkedMultiValueMap<String, String>();
327338
form.add("grant_type", "authorization_code");
328339
form.add("code", authorizationGrant);
329-
form.add("redirect_uri", buildRedirectURI(request));
340+
form.add("redirect_uri",
341+
buildRedirectURI(request, new String[] { "code" }));
342+
343+
// pass clientId and clientSecret in post of request
344+
form.add("client_id", clientId);
345+
form.add("client_secret", clientSecret);
346+
347+
348+
if (debug) {
349+
logger.debug("tokenEndpointURI = " + tokenEndpointURI);
350+
logger.debug("form = " + form);
351+
}
330352

331353
String jsonString = null;
332354

@@ -341,7 +363,8 @@ public Authentication attemptAuthentication(HttpServletRequest request,
341363
+ httpClientErrorException.getStatusText() + " : "
342364
+ httpClientErrorException.getMessage());
343365

344-
return null;
366+
throw new AuthenticationServiceException(
367+
"Unable to obtain Access Token.");
345368
}
346369

347370
JsonElement jsonRoot = new JsonParser().parse(jsonString);
@@ -355,7 +378,9 @@ public Authentication attemptAuthentication(HttpServletRequest request,
355378

356379
logger.error("Token Endpoint returned: " + error);
357380

358-
return null;
381+
throw new AuthenticationServiceException(
382+
"Unable to obtain Access Token. Token Endpoint returned: "
383+
+ error);
359384

360385
} else {
361386

@@ -376,7 +401,8 @@ public Authentication attemptAuthentication(HttpServletRequest request,
376401
logger.error("Problem parsing id_token: " + e);
377402
// e.printStackTrace();
378403

379-
return null;
404+
throw new AuthenticationServiceException(
405+
"Problem parsing id_token return from Token endpoint: " + e);
380406
}
381407

382408
} else {
@@ -385,7 +411,8 @@ public Authentication attemptAuthentication(HttpServletRequest request,
385411

386412
logger.error("Token Endpoint did not return a token_id");
387413

388-
return null;
414+
throw new AuthenticationServiceException(
415+
"Token Endpoint did not return a token_id");
389416
}
390417

391418
// Handle Check ID Endpoint interaction
@@ -418,7 +445,8 @@ public Authentication attemptAuthentication(HttpServletRequest request,
418445
+ httpClientErrorException.getStatusText()
419446
+ " : " + httpClientErrorException.getMessage());
420447

421-
return null;
448+
throw new AuthenticationServiceException(
449+
"Unable check token.");
422450
}
423451

424452
jsonRoot = new JsonParser().parse(jsonString);
@@ -453,29 +481,36 @@ public Authentication attemptAuthentication(HttpServletRequest request,
453481
+ NONCE_SIGNATURE_COOKIE_NAME
454482
+ " failed.");
455483

456-
return null;
484+
throw new AuthenticationServiceException(
485+
"Possible replay attack detected! "
486+
+ "The comparison of the nonce in the returned "
487+
+ "ID Token to the signed session "
488+
+ NONCE_SIGNATURE_COOKIE_NAME
489+
+ " failed.");
457490
}
458491

459492
} else {
460493
logger.error(NONCE_SIGNATURE_COOKIE_NAME
461494
+ " was found, but was null or empty.");
462495

463-
return null;
496+
throw new AuthenticationServiceException(NONCE_SIGNATURE_COOKIE_NAME
497+
+ " was found, but was null or empty.");
464498
}
465499

466500
} else {
467501

468502
logger.error(NONCE_SIGNATURE_COOKIE_NAME
469503
+ " cookie was not found.");
470504

471-
return null;
505+
throw new AuthenticationServiceException(NONCE_SIGNATURE_COOKIE_NAME
506+
+ " cookie was not found.");
472507
}
473508

474509
// Create an Authentication object for the token, and
475510
// return.
476511

477512
OpenIdConnectAuthenticationToken token = new OpenIdConnectAuthenticationToken(
478-
idToken, userId);
513+
userId, idToken);
479514

480515
Authentication authentication = this
481516
.getAuthenticationManager().authenticate(token);
@@ -495,7 +530,8 @@ public Authentication attemptAuthentication(HttpServletRequest request,
495530
urlVariables.put("response_type", "code");
496531
urlVariables.put("client_id", clientId);
497532
urlVariables.put("scope", scope);
498-
urlVariables.put("redirect_uri", buildRedirectURI(request));
533+
urlVariables.put("redirect_uri",
534+
buildRedirectURI(request, null));
499535

500536
// Create a string value used to associate a user agent session
501537
// with an ID Token to mitigate replay attacks. The value is
@@ -530,9 +566,15 @@ public Authentication attemptAuthentication(HttpServletRequest request,
530566
*
531567
* @param request
532568
* the current request which is being processed by this filter
533-
* @return The redirect_uri.
569+
* @param ingoreParameters
570+
* an array of parameter names to ignore.
571+
* @return
534572
*/
535-
private String buildRedirectURI(HttpServletRequest request) {
573+
private String buildRedirectURI(HttpServletRequest request,
574+
String[] ingoreParameters) {
575+
576+
List<String> ignore = (ingoreParameters != null) ? Arrays
577+
.asList(ingoreParameters) : null;
536578

537579
boolean isFirst = true;
538580

@@ -542,22 +584,25 @@ private String buildRedirectURI(HttpServletRequest request) {
542584
.hasMoreElements();) {
543585

544586
String name = (String) e.nextElement();
545-
// Assume for simplicity that there is only one value
546-
String value = request.getParameter(name);
547587

548-
if (value == null) {
549-
continue;
550-
}
588+
if ((ignore == null) || (!ignore.contains(name))) {
589+
// Assume for simplicity that there is only one value
590+
String value = request.getParameter(name);
551591

552-
if (isFirst) {
553-
sb.append("?");
554-
isFirst = false;
555-
}
592+
if (value == null) {
593+
continue;
594+
}
556595

557-
sb.append(name).append("=").append(value);
596+
if (isFirst) {
597+
sb.append("?");
598+
isFirst = false;
599+
}
558600

559-
if (e.hasMoreElements()) {
560-
sb.append("&");
601+
sb.append(name).append("=").append(value);
602+
603+
if (e.hasMoreElements()) {
604+
sb.append("&");
605+
}
561606
}
562607
}
563608

openid-connect-client/src/main/java/org/mitre/openid/connect/client/OpenIdConnectAuthenticationProvider.java

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,22 @@
44
import org.springframework.security.authentication.AuthenticationProvider;
55
import org.springframework.security.core.Authentication;
66
import org.springframework.security.core.AuthenticationException;
7+
import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
8+
import org.springframework.security.core.authority.mapping.NullAuthoritiesMapper;
9+
import org.springframework.security.core.userdetails.AuthenticationUserDetailsService;
10+
import org.springframework.security.core.userdetails.UserDetails;
11+
import org.springframework.util.Assert;
712

13+
/**
14+
* @author mjwalsh
15+
*
16+
*/
817
public class OpenIdConnectAuthenticationProvider implements
918
AuthenticationProvider, InitializingBean {
1019

20+
private AuthenticationUserDetailsService<OpenIdConnectAuthenticationToken> userDetailsService;
21+
private GrantedAuthoritiesMapper authoritiesMapper = new NullAuthoritiesMapper();
22+
1123
/*
1224
* (non-Javadoc)
1325
*
@@ -16,7 +28,8 @@ public class OpenIdConnectAuthenticationProvider implements
1628
*/
1729
@Override
1830
public void afterPropertiesSet() throws Exception {
19-
// TODO Auto-generated method stub
31+
Assert.notNull(this.userDetailsService,
32+
"The userDetailsService must be set");
2033
}
2134

2235
/*
@@ -26,16 +39,40 @@ public void afterPropertiesSet() throws Exception {
2639
* authenticate(org.springframework.security.core.Authentication)
2740
*/
2841
@Override
29-
public Authentication authenticate(Authentication authentication)
42+
public Authentication authenticate(final Authentication authentication)
3043
throws AuthenticationException {
3144

45+
if (!supports(authentication.getClass())) {
46+
return null;
47+
}
48+
3249
if (authentication instanceof OpenIdConnectAuthenticationToken) {
33-
return authentication;
50+
51+
OpenIdConnectAuthenticationToken token = (OpenIdConnectAuthenticationToken) authentication;
52+
53+
UserDetails userDetails = userDetailsService.loadUserDetails(token);
54+
55+
return new OpenIdConnectAuthenticationToken(userDetails,
56+
authoritiesMapper.mapAuthorities(userDetails
57+
.getAuthorities()), token.getUserId(),
58+
token.getIdToken());
3459
}
3560

3661
return null;
3762
}
3863

64+
/**
65+
* @param authoritiesMapper
66+
*/
67+
public void setAuthoritiesMapper(GrantedAuthoritiesMapper authoritiesMapper) {
68+
this.authoritiesMapper = authoritiesMapper;
69+
}
70+
71+
public void setUserDetailsService(
72+
AuthenticationUserDetailsService<OpenIdConnectAuthenticationToken> userDetailsService) {
73+
this.userDetailsService = userDetailsService;
74+
}
75+
3976
/*
4077
* (non-Javadoc)
4178
*
@@ -48,5 +85,4 @@ public boolean supports(Class<?> authentication) {
4885
return OpenIdConnectAuthenticationToken.class
4986
.isAssignableFrom(authentication);
5087
}
51-
5288
}

0 commit comments

Comments
 (0)