Skip to content

Commit 0c63b55

Browse files
committed
[PLINK-709] - Add option to redirect based on an exception.
1 parent 63b6324 commit 0c63b55

File tree

11 files changed

+412
-104
lines changed

11 files changed

+412
-104
lines changed
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* JBoss, Home of Professional Open Source
3+
*
4+
* Copyright 2013 Red Hat, Inc. and/or its affiliates.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
package org.picketlink.authentication;
20+
21+
22+
/**
23+
* <p>Thrown during the authentication process to indicate that the credential is expired.</p>
24+
*
25+
* @author Pedro Igor
26+
*/
27+
public class CredentialExpiredException extends AuthenticationException {
28+
29+
private static final long serialVersionUID = -6004476163990264247L;
30+
31+
public CredentialExpiredException(String message) {
32+
super(message);
33+
}
34+
35+
}

modules/base/api/src/main/java/org/picketlink/config/http/OutboundRedirectConfiguration.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,16 +33,18 @@ public class OutboundRedirectConfiguration implements Serializable {
3333
private static final long serialVersionUID = -3573074778328421432L;
3434

3535
private final String redirectUrl;
36+
private final Class<? extends Throwable> exceptionType;
3637
private Condition condition;
3738

38-
public OutboundRedirectConfiguration(String redirectUrl, Condition condition) {
39+
public OutboundRedirectConfiguration(String redirectUrl, Condition condition, Class<? extends Throwable> exceptionType) {
3940
this.redirectUrl = redirectUrl;
4041

4142
if (condition == null) {
4243
condition = OK;
4344
}
4445

4546
this.condition = condition;
47+
this.exceptionType = exceptionType;
4648
}
4749

4850
public String getRedirectUrl() {
@@ -53,6 +55,10 @@ public Condition getCondition() {
5355
return this.condition;
5456
}
5557

58+
public Class<? extends Throwable> getExceptionType() {
59+
return this.exceptionType;
60+
}
61+
5662
public static enum Condition {
5763
FORBIDDEN,
5864
OK,

modules/base/api/src/main/java/org/picketlink/config/http/OutboundRedirectConfigurationBuilder.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ public class OutboundRedirectConfigurationBuilder extends AbstractPathConfigurat
3232

3333
private String redirectUrl;
3434
private Condition condition;
35+
private Class<? extends Throwable> exceptionType;
3536

3637
OutboundRedirectConfigurationBuilder(PathConfigurationBuilder parentBuilder, String redirectUrl) {
3738
super(parentBuilder);
@@ -58,8 +59,14 @@ public OutboundRedirectConfigurationBuilder whenError() {
5859
return this;
5960
}
6061

62+
public OutboundRedirectConfigurationBuilder whenException(Class<? extends Throwable> exceptionType) {
63+
this.condition = Condition.ERROR;
64+
this.exceptionType = exceptionType;
65+
return this;
66+
}
67+
6168
@Override
6269
protected OutboundRedirectConfiguration create() {
63-
return new OutboundRedirectConfiguration(this.redirectUrl, this.condition);
70+
return new OutboundRedirectConfiguration(this.redirectUrl, this.condition, this.exceptionType);
6471
}
6572
}

modules/base/api/src/main/java/org/picketlink/config/http/PathConfiguration.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,22 @@ public String getRedirectUrl(OutboundRedirectConfiguration.Condition condition)
307307
return redirectUrl;
308308
}
309309

310+
public String getRedirectUrl(Class<? extends Throwable> exceptionType) {
311+
String redirectUrl = null;
312+
313+
if (hasGroup()) {
314+
redirectUrl = getGroupConfiguration().getRedirectUrl(exceptionType);
315+
}
316+
317+
for (OutboundRedirectConfiguration redirectConfiguration : this.redirects) {
318+
if (exceptionType.equals(redirectConfiguration.getExceptionType())) {
319+
return redirectConfiguration.getRedirectUrl();
320+
}
321+
}
322+
323+
return redirectUrl;
324+
}
325+
310326
public boolean hasRedirectWhen(OutboundRedirectConfiguration.Condition condition) {
311327
boolean hasRedirect = false;
312328

@@ -331,5 +347,4 @@ public Set<HttpMethod> getMethods() {
331347
public String toString() {
332348
return "UriConfiguration{" + "groupName='" + groupName + '\'' + ", uri='" + uri + '\'' + '}';
333349
}
334-
335350
}

modules/base/impl/src/main/java/org/picketlink/authentication/internal/IdmAuthenticator.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package org.picketlink.authentication.internal;
22

33
import org.picketlink.authentication.BaseAuthenticator;
4+
import org.picketlink.authentication.CredentialExpiredException;
45
import org.picketlink.authentication.LockedAccountException;
56
import org.picketlink.authentication.UnexpectedCredentialException;
67
import org.picketlink.credential.DefaultLoginCredentials;
@@ -66,6 +67,8 @@ public void authenticate() {
6667
setAccount(creds.getValidatedAccount());
6768
} else if (Credentials.Status.ACCOUNT_DISABLED.equals(creds.getStatus())) {
6869
throw new LockedAccountException("Account [" + this.credentials.getUserId() + "] is disabled.");
70+
} else if (Credentials.Status.EXPIRED.equals(creds.getStatus())) {
71+
throw new CredentialExpiredException("Credential is expired for Account [" + this.credentials.getUserId() + "].");
6972
}
7073
}
7174

modules/base/impl/src/main/java/org/picketlink/http/internal/SecurityFilter.java

Lines changed: 40 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -257,47 +257,57 @@ private void redirect(String redirectUrl, HttpServletRequest request, HttpServle
257257

258258
private void handleException(PathConfiguration pathConfiguration, HttpServletRequest request, HttpServletResponse response,
259259
Throwable exception) throws IOException {
260-
String redirectUrl = null;
261-
int statusCode;
260+
String redirectUrl = pathConfiguration.getRedirectUrl(exception.getClass());
261+
Throwable cause = exception.getCause();
262262

263-
if (HTTP_LOGGER.isDebugEnabled()) {
264-
HTTP_LOGGER.debugf("Handling exception [%s] for path [%s].", exception, request.getRequestURI());
263+
if (redirectUrl == null && cause != null) {
264+
redirectUrl = pathConfiguration.getRedirectUrl(cause.getClass());
265265
}
266266

267-
if (AuthenticationRequiredException.class.isInstance(exception)) {
268-
statusCode = SC_UNAUTHORIZED;
269-
} else if (AccessDeniedException.class.isInstance(exception)) {
270-
statusCode = SC_FORBIDDEN;
271-
272-
if (isSecured(pathConfiguration)) {
273-
redirectUrl = pathConfiguration.getRedirectUrl(FORBIDDEN);
274-
}
275-
} else if (MethodNotAllowedException.class.isInstance(exception)) {
276-
statusCode = SC_METHOD_NOT_ALLOWED;
277-
} else {
278-
statusCode = SC_INTERNAL_SERVER_ERROR;
267+
int statusCode;
279268

280-
if (isSecured(pathConfiguration)) {
281-
redirectUrl = pathConfiguration.getRedirectUrl(ERROR);
282-
}
269+
if (HTTP_LOGGER.isDebugEnabled()) {
270+
HTTP_LOGGER.debugf("Handling exception [%s] for path [%s].", exception, request.getRequestURI());
283271
}
284272

285273
if (redirectUrl != null) {
286274
redirect(redirectUrl, request, response);
287275
} else {
288-
String message = exception.getMessage();
276+
if (AuthenticationRequiredException.class.isInstance(exception)) {
277+
statusCode = SC_UNAUTHORIZED;
278+
} else if (AccessDeniedException.class.isInstance(exception)) {
279+
statusCode = SC_FORBIDDEN;
289280

290-
if (message == null) {
291-
message = "The server could not process your request.";
292-
}
281+
if (isSecured(pathConfiguration)) {
282+
redirectUrl = pathConfiguration.getRedirectUrl(FORBIDDEN);
283+
}
284+
} else if (MethodNotAllowedException.class.isInstance(exception)) {
285+
statusCode = SC_METHOD_NOT_ALLOWED;
286+
} else {
287+
statusCode = SC_INTERNAL_SERVER_ERROR;
293288

294-
if (HTTP_LOGGER.isEnabled(Logger.Level.ERROR)) {
295-
HTTP_LOGGER.errorf(exception,
296-
"Exception thrown during processing for path [%s]. Sending error with status code [%s].",
297-
request.getRequestURI(), statusCode);
289+
if (isSecured(pathConfiguration)) {
290+
redirectUrl = pathConfiguration.getRedirectUrl(ERROR);
291+
}
298292
}
299293

300-
response.sendError(statusCode, message);
294+
if (redirectUrl != null) {
295+
redirect(redirectUrl, request, response);
296+
} else {
297+
String message = exception.getMessage();
298+
299+
if (message == null) {
300+
message = "The server could not process your request.";
301+
}
302+
303+
if (HTTP_LOGGER.isEnabled(Logger.Level.ERROR)) {
304+
HTTP_LOGGER.errorf(exception,
305+
"Exception thrown during processing for path [%s]. Sending error with status code [%s].",
306+
request.getRequestURI(), statusCode);
307+
}
308+
309+
response.sendError(statusCode, message);
310+
}
301311
}
302312
}
303313

@@ -404,7 +414,7 @@ private boolean performCORSAuthorizationIfRequired(PathConfiguration pathConfigu
404414
}
405415

406416
private void performAuthenticationIfRequired(PathConfiguration pathConfiguration, Identity identity,
407-
HttpServletRequest request, HttpServletResponse response) throws IOException {
417+
HttpServletRequest request, HttpServletResponse response) throws Exception {
408418
HttpAuthenticationScheme authenticationScheme = getAuthenticationScheme(pathConfiguration, request);
409419

410420
if (authenticationScheme != null) {
@@ -437,6 +447,7 @@ private void performAuthenticationIfRequired(PathConfiguration pathConfiguration
437447
authenticationScheme.onPostAuthentication(request, response);
438448
} catch (AuthenticationException ae) {
439449
HTTP_LOGGER.authenticationFailed(creds.getUserId(), ae);
450+
throw ae;
440451
}
441452
}
442453
} else {

modules/base/impl/src/main/java/org/picketlink/internal/AbstractIdentity.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ public AuthenticationResult login() {
156156

157157
handleUnsuccesfulLoginAttempt(null);
158158
return AuthenticationResult.FAILED;
159-
} catch (Throwable e) {
159+
} catch (Exception e) {
160160
handleUnsuccesfulLoginAttempt(e);
161161

162162
if (AuthenticationException.class.isInstance(e)) {
@@ -192,8 +192,7 @@ protected void handleUnsuccesfulLoginAttempt(Throwable e) {
192192
}
193193

194194
if (AUTHENTICATION_LOGGER.isDebugEnabled()) {
195-
AUTHENTICATION_LOGGER.debugf("Authentication failed for credentials [%s]. User id is [%s].", this.loginCredential
196-
.getCredential(), this.loginCredential.getUserId(), e);
195+
AUTHENTICATION_LOGGER.authenticationFailed(this.loginCredential.getUserId(), e);
197196
}
198197

199198
eventBridge.fireEvent(new LoginFailedEvent(e));

0 commit comments

Comments
 (0)