use of com.sun.identity.authentication.spi.RedirectCallback in project OpenAM by OpenRock.
the class RestAuthRedirectCallbackHandlerTest method shouldSerialiseToJsonCorrectly.
@Test
public void shouldSerialiseToJsonCorrectly() throws Exception {
// Given
RedirectCallback redirectCallback = mock(RedirectCallback.class);
final Map<String, String> redirectData = Collections.singletonMap("foo", "bar");
given(redirectCallback.getRedirectUrl()).willReturn("REDIRECT_URL");
given(redirectCallback.getMethod()).willReturn("REDIRECT_METHOD");
given(redirectCallback.getRedirectData()).willReturn(redirectData);
// When
// Round-trip via Jackson to ensure actual JSON produced by CREST would be correct. OPENAM-7143.
String json = JsonValueBuilder.getObjectMapper().writeValueAsString(restAuthRedirectCallbackHandler.convertToJson(redirectCallback, 1).getObject());
JsonValue parsed = JsonValueBuilder.toJsonValue(json);
// Then
assertThat(parsed).stringAt("/type").isEqualTo("RedirectCallback");
assertThat(parsed).hasArray("/output").hasSize(4);
assertThat(parsed).hasObject("/output/0").containsExactly(entry("name", "redirectUrl"), entry("value", "REDIRECT_URL"));
assertThat(parsed).hasObject("/output/1").containsExactly(entry("name", "redirectMethod"), entry("value", "REDIRECT_METHOD"));
assertThat(parsed).hasObject("/output/2").containsExactly(entry("name", "trackingCookie"), entry("value", false));
assertThat(parsed).hasObject("/output/3").containsExactly(entry("name", "redirectData"), entry("value", redirectData));
}
use of com.sun.identity.authentication.spi.RedirectCallback in project OpenAM by OpenRock.
the class AuthXMLUtils method getXMLForCallbacks.
/**
* TODO-JAVADOC
*/
public static String getXMLForCallbacks(Callback[] callbacks) {
if (callbacks == null) {
return ("");
}
// Construct the xml string
StringBuilder xmlString = new StringBuilder();
xmlString.append(AuthXMLTags.CALLBACKS_BEGIN).append(AuthXMLTags.SPACE).append(AuthXMLTags.LENGTH).append(AuthXMLTags.EQUAL).append(AuthXMLTags.QUOTE).append(callbacks.length).append(AuthXMLTags.QUOTE).append(AuthXMLTags.ELEMENT_END);
for (int i = 0; i < callbacks.length; i++) {
if (callbacks[i] instanceof HiddenValueCallback) {
HiddenValueCallback hiddenValueCallback = (HiddenValueCallback) callbacks[i];
xmlString.append(getHiddenValueCallbackXML(hiddenValueCallback));
} else if (callbacks[i] instanceof NameCallback) {
NameCallback nameCallback = (NameCallback) callbacks[i];
xmlString.append(getNameCallbackXML(nameCallback));
} else if (callbacks[i] instanceof PasswordCallback) {
PasswordCallback passwordCallback = (PasswordCallback) callbacks[i];
xmlString.append(getPasswordCallbackXML(passwordCallback));
} else if (callbacks[i] instanceof ChoiceCallback) {
ChoiceCallback choiceCallback = (ChoiceCallback) callbacks[i];
xmlString.append(getChoiceCallbackXML(choiceCallback));
} else if (callbacks[i] instanceof ConfirmationCallback) {
ConfirmationCallback conCallback = (ConfirmationCallback) callbacks[i];
xmlString.append(getConfirmationCallbackXML(conCallback));
} else if (callbacks[i] instanceof TextInputCallback) {
TextInputCallback textInputCallback = (TextInputCallback) callbacks[i];
xmlString.append(getTextInputCallbackXML(textInputCallback));
} else if (callbacks[i] instanceof TextOutputCallback) {
TextOutputCallback textOutputCallback = (TextOutputCallback) callbacks[i];
xmlString.append(getTextOutputCallbackXML(textOutputCallback));
} else if (callbacks[i] instanceof PagePropertiesCallback) {
PagePropertiesCallback pagePCallback = (PagePropertiesCallback) callbacks[i];
xmlString.append(getPagePropertiesCallbackXML(pagePCallback));
} else if (callbacks[i] instanceof LanguageCallback) {
LanguageCallback lc = (LanguageCallback) callbacks[i];
xmlString.append(getLanguageCallbackXML(lc));
} else if (callbacks[i] instanceof X509CertificateCallback) {
X509CertificateCallback xc = (X509CertificateCallback) callbacks[i];
xmlString.append(getX509CertificateCallbackXML(xc));
} else if (callbacks[i] instanceof HttpCallback) {
HttpCallback hc = (HttpCallback) callbacks[i];
xmlString.append(getHttpCallbackXML(hc));
} else if (callbacks[i] instanceof DSAMECallbackInterface) {
DSAMECallbackInterface dsameCallback = (DSAMECallbackInterface) callbacks[i];
xmlString.append(getCustomCallbackXML(dsameCallback));
} else if (callbacks[i] instanceof RedirectCallback) {
RedirectCallback redirectCallback = (RedirectCallback) callbacks[i];
xmlString.append(getRedirectCallbackXML(redirectCallback));
} else {
AuthenticationCallbackXMLHelper callbackXMLHelper = AuthenticationCallbackXMLHelperFactory.getCallbackXMLHelper();
if (callbackXMLHelper != null) {
xmlString.append(callbackXMLHelper.getAuthenticationCallbackXML(callbacks[i]));
}
}
}
xmlString.append(AuthXMLTags.CALLBACKS_END);
return (xmlString.toString());
}
use of com.sun.identity.authentication.spi.RedirectCallback in project OpenAM by OpenRock.
the class RestAuthenticationHandler method processAuthentication.
/**
* Using the given LoginProcess will process the authentication by getting the required callbacks and either
* completing and submitting them or sending the requirements back to the client as JSON. If the authentication
* process has completed it will then check the completion status and will either return an error or the SSO Token
* Id to the client.
*
* @param request The HttpServletRequest.
* @param response The HttpServletResponse.
* @param postBody The post body of the request.
* @param loginProcess The LoginProcess used to track the login.
* @param loginConfiguration The LoginConfiguration used to configure the login process.
* @return A ResponseBuilder which contains the contents of the response to return to the client.
* @throws AuthLoginException If there is a problem submitting the callbacks.
* @throws SignatureException If there is a problem creating the JWT to use in the response to the client.
*/
private JsonValue processAuthentication(HttpServletRequest request, HttpServletResponse response, JsonValue postBody, String authId, LoginProcess loginProcess, LoginConfiguration loginConfiguration) throws AuthLoginException, SignatureException, RestAuthException {
switch(loginProcess.getLoginStage()) {
case REQUIREMENTS_WAITING:
{
Callback[] callbacks = loginProcess.getCallbacks();
JsonValue jsonCallbacks;
try {
if (callbacks.length == 1 && callbacks[0] instanceof RedirectCallback && postBody != null) {
jsonCallbacks = null;
} else {
jsonCallbacks = handleCallbacks(request, response, postBody, callbacks);
}
} catch (RestAuthResponseException e) {
// Include the authId in the JSON response.
if (authId == null) {
authId = authIdHelper.createAuthId(loginConfiguration, loginProcess.getAuthContext());
}
e.getJsonResponse().put(AUTH_ID, authId);
AuditRequestContext.putProperty(AUTH_ID, authId);
throw e;
}
if (jsonCallbacks != null && jsonCallbacks.size() > 0) {
JsonValue jsonValue = createJsonCallbackResponse(authId, loginConfiguration, loginProcess, jsonCallbacks);
return jsonValue;
} else {
loginProcess = loginProcess.next(callbacks);
return processAuthentication(request, response, null, authId, loginProcess, loginConfiguration);
}
}
case COMPLETE:
{
loginProcess.cleanup();
if (loginProcess.isSuccessful()) {
// send token to client
JsonObject jsonResponseObject = JsonValueBuilder.jsonValue();
SSOToken ssoToken = loginProcess.getSSOToken();
if (ssoToken != null) {
String tokenId = ssoToken.getTokenID().toString();
jsonResponseObject.put(TOKEN_ID, tokenId);
AuditRequestContext.putProperty(TOKEN_ID, tokenId);
} else {
jsonResponseObject.put("message", "Authentication Successful");
}
String gotoUrl = urlValidator.getRedirectUrl(loginProcess.getOrgDN(), urlValidator.getValueFromJson(postBody, RedirectUrlValidator.GOTO), loginProcess.getSuccessURL());
jsonResponseObject.put("successUrl", gotoUrl);
return jsonResponseObject.build();
} else {
// send Error to client
AuthenticationContext authContext = loginProcess.getAuthContext();
String errorCode = authContext.getErrorCode();
String errorMessage = authContext.getErrorMessage();
throw new RestAuthErrorCodeException(errorCode, errorMessage);
}
}
}
// This should never happen
throw new RestAuthException(ResourceException.INTERNAL_ERROR, "Unknown Authentication State!");
}
use of com.sun.identity.authentication.spi.RedirectCallback in project OpenAM by OpenRock.
the class OAuth method process.
public int process(Callback[] callbacks, int state) throws LoginException {
OAuthUtil.debugMessage("process: state = " + state);
HttpServletRequest request = getHttpServletRequest();
HttpServletResponse response = getHttpServletResponse();
if (request == null) {
OAuthUtil.debugError("OAuth.process(): The request was null, this is " + "an interactive module");
return ISAuthConstants.LOGIN_IGNORE;
}
// We are being redirected back from an OAuth 2 Identity Provider
String code = request.getParameter(PARAM_CODE);
if (code != null) {
OAuthUtil.debugMessage("OAuth.process(): GOT CODE: " + code);
state = GET_OAUTH_TOKEN_STATE;
}
// The Proxy is used to return with a POST to the module
proxyURL = config.getProxyURL();
switch(state) {
case ISAuthConstants.LOGIN_START:
{
config.validateConfiguration();
serverName = request.getServerName();
StringBuilder originalUrl = new StringBuilder();
String requestedQuery = request.getQueryString();
String realm = null;
String authCookieName = AuthUtils.getAuthCookieName();
final XUIState xuiState = InjectorHolder.getInstance(XUIState.class);
if (xuiState.isXUIEnabled()) {
// When XUI is in use the request URI points to the authenticate REST endpoint, which shouldn't be
// presented to the end-user, hence we use the contextpath only and rely on index.html and the
// XUIFilter to direct the user towards the XUI.
originalUrl.append(request.getContextPath());
// the realm parameter was not present on the querystring, then we add it there.
if (requestedQuery != null && !requestedQuery.contains("realm=")) {
realm = request.getParameter("realm");
}
} else {
//In case of legacy UI the request URI will be /openam/UI/Login, which is safe to use.
originalUrl.append(request.getRequestURI());
}
if (StringUtils.isNotEmpty(realm)) {
originalUrl.append("?realm=").append(URLEncDec.encode(realm));
}
if (requestedQuery != null) {
if (requestedQuery.endsWith(authCookieName + "=")) {
requestedQuery = requestedQuery.substring(0, requestedQuery.length() - authCookieName.length() - 1);
}
originalUrl.append(originalUrl.indexOf("?") == -1 ? '?' : '&');
originalUrl.append(requestedQuery);
}
// Find the domains for which we are configured
Set<String> domains = AuthClientUtils.getCookieDomainsForRequest(request);
String ProviderLogoutURL = config.getLogoutServiceUrl();
String csrfStateTokenId = RandomStringUtils.randomAlphanumeric(32);
String csrfState = createAuthorizationState();
Token csrfStateToken = new Token(csrfStateTokenId, TokenType.GENERIC);
csrfStateToken.setAttribute(CoreTokenField.STRING_ONE, csrfState);
try {
ctsStore.create(csrfStateToken);
} catch (CoreTokenException e) {
OAuthUtil.debugError("OAuth.process(): Authorization redirect failed to be sent because the state " + "could not be stored");
throw new AuthLoginException("OAuth.process(): Authorization redirect failed to be sent because " + "the state could not be stored", e);
}
// when retrieving the token
for (String domain : domains) {
CookieUtils.addCookieToResponse(response, CookieUtils.newCookie(COOKIE_PROXY_URL, proxyURL, "/", domain));
CookieUtils.addCookieToResponse(response, CookieUtils.newCookie(COOKIE_ORIG_URL, originalUrl.toString(), "/", domain));
CookieUtils.addCookieToResponse(response, CookieUtils.newCookie(NONCE_TOKEN_ID, csrfStateTokenId, "/", domain));
if (ProviderLogoutURL != null && !ProviderLogoutURL.isEmpty()) {
CookieUtils.addCookieToResponse(response, CookieUtils.newCookie(COOKIE_LOGOUT_URL, ProviderLogoutURL, "/", domain));
}
}
// The Proxy is used to return with a POST to the module
setUserSessionProperty(ISAuthConstants.FULL_LOGIN_URL, originalUrl.toString());
setUserSessionProperty(SESSION_LOGOUT_BEHAVIOUR, config.getLogoutBhaviour());
String authServiceUrl = config.getAuthServiceUrl(proxyURL, csrfState);
OAuthUtil.debugMessage("OAuth.process(): New RedirectURL=" + authServiceUrl);
Callback[] callbacks1 = getCallback(2);
RedirectCallback rc = (RedirectCallback) callbacks1[0];
RedirectCallback rcNew = new RedirectCallback(authServiceUrl, null, "GET", rc.getStatusParameter(), rc.getRedirectBackUrlCookieName());
rcNew.setTrackingCookie(true);
replaceCallback(2, 0, rcNew);
return GET_OAUTH_TOKEN_STATE;
}
case GET_OAUTH_TOKEN_STATE:
{
final String csrfState;
if (request.getParameter("jsonContent") != null) {
final JsonValue jval = JsonValueBuilder.toJsonValue(request.getParameter("jsonContent"));
csrfState = jval.get("state").asString();
code = jval.get(PARAM_CODE).asString();
} else {
csrfState = request.getParameter("state");
code = request.getParameter(PARAM_CODE);
}
if (csrfState == null) {
OAuthUtil.debugError("OAuth.process(): Authorization call-back failed because there was no state " + "parameter");
throw new AuthLoginException(BUNDLE_NAME, "noState", null);
}
try {
Token csrfStateToken = ctsStore.read(OAuthUtil.findCookie(request, NONCE_TOKEN_ID));
ctsStore.deleteAsync(csrfStateToken);
String expectedCsrfState = csrfStateToken.getValue(CoreTokenField.STRING_ONE);
if (!expectedCsrfState.equals(csrfState)) {
OAuthUtil.debugError("OAuth.process(): Authorization call-back failed because the state parameter " + "contained an unexpected value");
throw new AuthLoginException(BUNDLE_NAME, "incorrectState", null);
}
// We are being redirected back from an OAuth 2 Identity Provider
if (code == null || code.isEmpty()) {
OAuthUtil.debugMessage("OAuth.process(): LOGIN_IGNORE");
return ISAuthConstants.LOGIN_START;
}
validateInput("code", code, "HTTPParameterValue", 2000, false);
OAuthUtil.debugMessage("OAuth.process(): code parameter: " + code);
String tokenSvcResponse = getContent(config.getTokenServiceUrl(code, proxyURL), null);
OAuthUtil.debugMessage("OAuth.process(): token=" + tokenSvcResponse);
JwtClaimsSet jwtClaims = null;
String idToken = null;
if (config.isOpenIDConnect()) {
idToken = extractToken(ID_TOKEN, tokenSvcResponse);
JwtHandler jwtHandler = new JwtHandler(jwtHandlerConfig);
try {
jwtClaims = jwtHandler.validateJwt(idToken);
} catch (RuntimeException | AuthLoginException e) {
debug.warning("Cannot validate JWT", e);
throw e;
}
if (!JwtHandler.isIntendedForAudience(config.getClientId(), jwtClaims)) {
OAuthUtil.debugError("OAuth.process(): ID token is not for this client as audience.");
throw new AuthLoginException(BUNDLE_NAME, "audience", null);
}
}
String token = extractToken(PARAM_ACCESS_TOKEN, tokenSvcResponse);
setUserSessionProperty(SESSION_OAUTH_TOKEN, token);
String profileSvcResponse = null;
if (StringUtils.isNotEmpty(config.getProfileServiceUrl())) {
profileSvcResponse = getContent(config.getProfileServiceUrl(), "Bearer " + token);
OAuthUtil.debugMessage("OAuth.process(): Profile Svc response: " + profileSvcResponse);
}
String realm = getRequestOrg();
if (realm == null) {
realm = "/";
}
AccountProvider accountProvider = instantiateAccountProvider();
AttributeMapper accountAttributeMapper = instantiateAccountMapper();
Map<String, Set<String>> userNames = getAttributes(profileSvcResponse, config.getAccountMapperConfig(), accountAttributeMapper, jwtClaims);
String user = null;
if (!userNames.isEmpty()) {
user = getUser(realm, accountProvider, userNames);
}
if (user == null && !config.getCreateAccountFlag()) {
authenticatedUser = getDynamicUser(userNames);
if (authenticatedUser != null) {
if (config.getSaveAttributesToSessionFlag()) {
Map<String, Set<String>> attributes = getAttributesMap(profileSvcResponse, jwtClaims);
saveAttributes(attributes);
}
OAuthUtil.debugMessage("OAuth.process(): LOGIN_SUCCEED " + "with user " + authenticatedUser);
storeUsernamePasswd(authenticatedUser, null);
return ISAuthConstants.LOGIN_SUCCEED;
} else {
throw new AuthLoginException("No user mapped!");
}
}
if (user == null && config.getCreateAccountFlag()) {
if (config.getPromptPasswordFlag()) {
setUserSessionProperty(PROFILE_SERVICE_RESPONSE, profileSvcResponse);
if (config.isOpenIDConnect()) {
setUserSessionProperty(OPENID_TOKEN, idToken);
}
return SET_PASSWORD_STATE;
} else {
authenticatedUser = provisionAccountNow(accountProvider, realm, profileSvcResponse, getRandomData(), jwtClaims);
if (authenticatedUser != null) {
OAuthUtil.debugMessage("User created: " + authenticatedUser);
storeUsernamePasswd(authenticatedUser, null);
return ISAuthConstants.LOGIN_SUCCEED;
} else {
return ISAuthConstants.LOGIN_IGNORE;
}
}
}
if (user != null) {
authenticatedUser = user;
OAuthUtil.debugMessage("OAuth.process(): LOGIN_SUCCEED " + "with user " + authenticatedUser);
if (config.getSaveAttributesToSessionFlag()) {
Map<String, Set<String>> attributes = getAttributesMap(profileSvcResponse, jwtClaims);
saveAttributes(attributes);
}
storeUsernamePasswd(authenticatedUser, null);
return ISAuthConstants.LOGIN_SUCCEED;
}
} catch (JSONException je) {
OAuthUtil.debugError("OAuth.process(): JSONException: " + je.getMessage());
throw new AuthLoginException(BUNDLE_NAME, "json", null, je);
} catch (SSOException ssoe) {
OAuthUtil.debugError("OAuth.process(): SSOException: " + ssoe.getMessage());
throw new AuthLoginException(BUNDLE_NAME, "ssoe", null, ssoe);
} catch (IdRepoException ire) {
OAuthUtil.debugError("OAuth.process(): IdRepoException: " + ire.getMessage());
throw new AuthLoginException(BUNDLE_NAME, "ire", null, ire);
} catch (CoreTokenException e) {
OAuthUtil.debugError("OAuth.process(): Authorization call-back failed because the state parameter " + "contained an unexpected value");
throw new AuthLoginException(BUNDLE_NAME, "incorrectState", null, e);
}
break;
}
case SET_PASSWORD_STATE:
{
if (!config.getCreateAccountFlag()) {
return ISAuthConstants.LOGIN_IGNORE;
}
userPassword = request.getParameter(PARAM_TOKEN1);
validateInput(PARAM_TOKEN1, userPassword, "HTTPParameterValue", 512, false);
String userPassword2 = request.getParameter(PARAM_TOKEN2);
validateInput(PARAM_TOKEN2, userPassword2, "HTTPParameterValue", 512, false);
if (!userPassword.equals(userPassword2)) {
OAuthUtil.debugWarning("OAuth.process(): Passwords did not match!");
return SET_PASSWORD_STATE;
}
String terms = request.getParameter("terms");
if (!terms.equalsIgnoreCase("accept")) {
return SET_PASSWORD_STATE;
}
String profileSvcResponse = getUserSessionProperty("ATTRIBUTES");
data = getRandomData();
String mail = getMail(profileSvcResponse, config.getMailAttribute());
OAuthUtil.debugMessage("Mail found = " + mail);
try {
OAuthUtil.sendEmail(config.getEmailFrom(), mail, data, config.getSMTPConfig(), bundle, proxyURL);
} catch (NoEmailSentException ex) {
OAuthUtil.debugError("No mail sent due to error", ex);
throw new AuthLoginException("Aborting authentication, because " + "the mail could not be sent due to a mail sending error");
}
OAuthUtil.debugMessage("User to be created, we need to activate: " + data);
return CREATE_USER_STATE;
}
case CREATE_USER_STATE:
{
String activation = request.getParameter(PARAM_ACTIVATION);
validateInput(PARAM_ACTIVATION, activation, "HTTPParameterValue", 512, false);
OAuthUtil.debugMessage("code entered by the user: " + activation);
if (activation == null || activation.isEmpty() || !activation.trim().equals(data.trim())) {
return CREATE_USER_STATE;
}
String profileSvcResponse = getUserSessionProperty(PROFILE_SERVICE_RESPONSE);
String idToken = getUserSessionProperty(ID_TOKEN);
String realm = getRequestOrg();
if (realm == null) {
realm = "/";
}
OAuthUtil.debugMessage("Got Attributes: " + profileSvcResponse);
AccountProvider accountProvider = instantiateAccountProvider();
JwtClaimsSet jwtClaims = null;
if (idToken != null) {
jwtClaims = new JwtHandler(jwtHandlerConfig).getJwtClaims(idToken);
}
authenticatedUser = provisionAccountNow(accountProvider, realm, profileSvcResponse, userPassword, jwtClaims);
if (authenticatedUser != null) {
OAuthUtil.debugMessage("User created: " + authenticatedUser);
storeUsernamePasswd(authenticatedUser, null);
return ISAuthConstants.LOGIN_SUCCEED;
} else {
return ISAuthConstants.LOGIN_IGNORE;
}
}
default:
{
OAuthUtil.debugError("OAuth.process(): Illegal State");
return ISAuthConstants.LOGIN_IGNORE;
}
}
throw new AuthLoginException(BUNDLE_NAME, "unknownState", null);
}
use of com.sun.identity.authentication.spi.RedirectCallback in project OpenAM by OpenRock.
the class SAML2 method configureGetRedirectCallback.
/**
* Generates the redirect from SAML2 auth module to IDP as GET.
*/
private void configureGetRedirectCallback(final String redirectUrl, RedirectCallback redirectCallback) throws AuthLoginException {
final RedirectCallback rcNew = new RedirectCallback(redirectUrl, null, "GET", redirectCallback.getStatusParameter(), redirectCallback.getRedirectBackUrlCookieName());
Map<String, String> redirectData = rcNew.getRedirectData();
rcNew.setRedirectData(redirectData);
rcNew.setTrackingCookie(true);
replaceCallback(REDIRECT, REDIRECT_CALLBACK, rcNew);
}
Aggregations