public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException { HttpServletResponse httpResponse = (HttpServletResponse) response; // compute a nonce (do not use remote IP address due to proxy farms) // format of nonce is: // base64(expirationTime + ":" + md5Hex(expirationTime + ":" + key)) long expiryTime = System.currentTimeMillis() + (super.getNonceValiditySeconds() * 1000); String signatureValue = DigestUtils.md5DigestAsHex(new String( expiryTime + ":" + super.getKey()).getBytes()); String nonceValue = expiryTime + ":" + signatureValue; String nonceValueBase64 = new String(Base64.encode(nonceValue .getBytes())); // qop is quality of protection, as defined by RFC 2617. // we do not use opaque due to IE violation of RFC 2617 in not // representing opaque on subsequent requests in same session. String authenticateHeader = "DigestCustom realm=\"" + super.getRealmName() + "\", " + "qop=\"auth\", nonce=\"" + nonceValueBase64 + "\""; if (authException instanceof NonceExpiredException) { authenticateHeader = authenticateHeader + ", stale=\"true\""; } if (logger.isDebugEnabled()) { logger.debug("WWW-Authenticate header sent to user agent: " + authenticateHeader); } httpResponse.addHeader("WWW-Authenticate", authenticateHeader); httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, authException.getMessage()); }
private String doHerokuSingleSignOn(String externalId, long timestampSeconds, String token, String email) throws AuthenticationException { String expectedToken = makeHerokuSsoToken(externalId, timestampSeconds); logger.debug("id={}, token={}, timestamp={}, expectedToken={}", externalId, token, timestampSeconds, expectedToken); long nowSeconds = System.currentTimeMillis() / 1000L; if (timestampSeconds > nowSeconds + 60) { throw new NonceExpiredException("Timestamp is too far into the future"); } if (timestampSeconds < nowSeconds - 5 * 60) { throw new NonceExpiredException("Timestamp is too old"); } if (!expectedToken.equals(token)) { throw new BadCredentialsException("Invalid token"); } CustomerData customerData = customerService.getCustomerDataByExternalId(externalId); customerService.registerLogin(CustomerService.LoginRequest.builder() .customerId(customerData.getCustomerId()) .source(customerData.getSource()) .email(email) .build()); return webappTokenProvider.createWebappToken( customerData.getCustomerId(), WebappCredentials.builder() .externalId(externalId) .customerName(customerData.getCustomerName()) .email(email) .source(customerData.getSource()) .build()); }
private String getFailureUrl(AuthenticationException exception) { if (exception instanceof NonceExpiredException) { return expiredUrl; } return defaultFailureUrl; }
@Override public void commence( HttpServletRequest request, HttpServletResponse response, org.springframework.security.core.AuthenticationException authException) throws IOException, ServletException { //super.commence(request, response, authException); HttpServletResponse httpResponse = (HttpServletResponse) response; // compute a nonce (do not use remote IP address due to proxy farms) // format of nonce is: // base64(expirationTime + ":" + md5Hex(expirationTime + ":" + key)) long expiryTime = System.currentTimeMillis() + (getNonceValiditySeconds() * 1000); String signatureValue = DigestUtils.md5Hex(expiryTime + ":" + getKey()); String nonceValue = expiryTime + ":" + signatureValue; String nonceValueBase64 = new String(Base64.encode(nonceValue.getBytes())); // qop is quality of protection, as defined by RFC 2617. // we do not use opaque due to IE violation of RFC 2617 in not // representing opaque on subsequent requests in same session. String authenticateHeader = "Digest realm=\"" + getRealmName() + "\", " + "qop=\"auth\", nonce=\"" + nonceValueBase64 + "\""; if (authException instanceof NonceExpiredException) { authenticateHeader = authenticateHeader + ", stale=\"true\""; } httpResponse.addHeader("WWW-Authenticate", authenticateHeader); //old HTML response //httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, authException.getMessage()); //custom response for digest authentication httpResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED); httpResponse.setContentType("application/json"); httpResponse.setCharacterEncoding("UTF-8"); httpResponse.getWriter().write("{\"error\":\"Authentication failed, wrong credentials for HTTP-Digest authentication\"}"); }