Skip to content

Commit c1cf96f

Browse files
committed
Update login web flow to handle param "errorSouce"
1 parent e637ff4 commit c1cf96f

10 files changed

Lines changed: 99 additions & 21 deletions

File tree

etc/cas/config/cas.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ cas.logout.remove-descendant-tickets=false
7171
#
7272
cas.authn.osf-url.home=https://{{ .Values.osfDomain }}/
7373
cas.authn.osf-url.dashboard=https://{{ .Values.osfDomain }}/dashboard/
74+
cas.authn.osf-url.login-with-next=https://{{ .Values.osfDomain }}/login?next=
7475
cas.authn.osf-url.logout=https://{{ .Values.osfDomain }}/logout/
7576
cas.authn.osf-url.resend-confirmation=https://{{ .Values.osfDomain }}/resend/
7677
cas.authn.osf-url.forgot-password=https://{{ .Values.osfDomain }}/forgotpassword/

etc/cas/config/local/cas-local.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ cas.logout.remove-descendant-tickets=false
7272
#
7373
cas.authn.osf-url.home=http://localhost:5000/
7474
cas.authn.osf-url.dashboard=http://localhost:5000/dashboard/
75+
cas.authn.osf-url.login-with-next=http://localhost:5000/login?next=
7576
cas.authn.osf-url.logout=http://localhost:5000/logout/
7677
cas.authn.osf-url.resend-confirmation=http://localhost:5000/resend/
7778
cas.authn.osf-url.forgot-password=http://localhost:5000/forgotpassword/

src/main/java/io/cos/cas/osf/configuration/model/OsfUrlProperties.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
import lombok.experimental.Accessors;
66

77
import java.io.Serializable;
8+
import java.net.URLEncoder;
9+
import java.nio.charset.StandardCharsets;
810

911
/**
1012
* This is {@link OsfUrlProperties}.
@@ -39,6 +41,11 @@ public class OsfUrlProperties implements Serializable {
3941
*/
4042
private String register;
4143

44+
/**
45+
* OSF login endpoint with "?next=".
46+
*/
47+
private String loginWithNext;
48+
4249
/**
4350
* OSF logout endpoint URL.
4451
*/
@@ -88,4 +95,11 @@ public class OsfUrlProperties implements Serializable {
8895
* OSF / COS donation page URL.
8996
*/
9097
private String donate;
98+
99+
/**
100+
* Build the default service URL using OSF login endpoint with OSF home page as destination.
101+
*/
102+
public String constructDefaultServiceUrl() {
103+
return loginWithNext + URLEncoder.encode(home, StandardCharsets.UTF_8);
104+
}
91105
}

src/main/java/io/cos/cas/osf/web/flow/configurer/OsfCasLoginWebflowConfigurer.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ protected void createDefaultViewStates(final Flow flow) {
8181
createTwoFactorLoginFormView(flow);
8282
createInstitutionLoginView(flow);
8383
createOrcidLoginAutoRedirectView(flow);
84+
createDefaultServiceLoginAutoRedirectView(flow);
8485
createOsfCasAuthenticationExceptionViewStates(flow);
8586
}
8687

@@ -324,6 +325,11 @@ private void createOsfDefaultLoginCheckAction(final Flow flow) {
324325
OsfCasWebflowConstants.TRANSITION_ID_ORCID_LOGIN_AUTO_REDIRECT,
325326
OsfCasWebflowConstants.VIEW_ID_ORCID_LOGIN_AUTO_REDIRECT
326327
);
328+
createTransitionForState(
329+
action,
330+
OsfCasWebflowConstants.TRANSITION_ID_DEFAULT_SERVICE_LOGIN_AUTO_REDIRECT,
331+
OsfCasWebflowConstants.VIEW_ID_DEFAULT_SERVICE_LOGIN_AUTO_REDIRECT
332+
);
327333
createTransitionForState(
328334
action,
329335
CasWebflowConstants.TRANSITION_ID_ERROR,
@@ -434,6 +440,19 @@ protected void createOrcidLoginAutoRedirectView(final Flow flow) {
434440
);
435441
}
436442

443+
/**
444+
* Create the ORCiD login auto-redirect view to support the OSF feature "sign-up via ORCiD".
445+
*
446+
* @param flow the flow
447+
*/
448+
protected void createDefaultServiceLoginAutoRedirectView(final Flow flow) {
449+
createViewState(
450+
flow,
451+
OsfCasWebflowConstants.VIEW_ID_DEFAULT_SERVICE_LOGIN_AUTO_REDIRECT,
452+
OsfCasWebflowConstants.VIEW_ID_DEFAULT_SERVICE_LOGIN_AUTO_REDIRECT
453+
);
454+
}
455+
437456
/**
438457
* Create the institution SSO init view state to support the OSF feature "sign-in via institutions".
439458
*

src/main/java/io/cos/cas/osf/web/flow/login/OsfAbstractLoginPreparationAction.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88
import org.springframework.webflow.execution.Event;
99
import org.springframework.webflow.execution.RequestContext;
1010

11+
import java.util.Arrays;
12+
import java.util.LinkedList;
13+
import java.util.List;
14+
1115
/**
1216
* This is {@link OsfAbstractLoginPreparationAction}.
1317
*
@@ -39,6 +43,10 @@ public abstract class OsfAbstractLoginPreparationAction extends AbstractAuthenti
3943

4044
protected static final String PARAMETER_ORCID_REDIRECT_VALUE = "true";
4145

46+
protected static final String PARAMETER_ERROR_SOURCE = "errorSource";
47+
48+
protected static final List<String> EXPECTED_ERROR_CODES = new LinkedList<>(Arrays.asList("401", "403", "404", "405", "423"));
49+
4250
public OsfAbstractLoginPreparationAction(
4351
final CasDelegatingWebflowEventResolver initialAuthenticationAttemptWebflowEventResolver,
4452
final CasWebflowEventResolver serviceTicketRequestWebflowEventResolver,

src/main/java/io/cos/cas/osf/web/flow/login/OsfCasPreInitialFlowSetupAction.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import io.cos.cas.osf.configuration.model.OsfUrlProperties;
44

5+
import io.cos.cas.osf.web.flow.support.OsfCasWebflowConstants;
56
import lombok.RequiredArgsConstructor;
67
import lombok.extern.slf4j.Slf4j;
78

@@ -22,17 +23,16 @@
2223
@Slf4j
2324
public class OsfCasPreInitialFlowSetupAction extends AbstractAction {
2425

25-
private static final String OSF_URL_FLOW_PARAMETER = "osfUrl";
26-
2726
@NotNull
2827
private final OsfUrlProperties osfUrlProperties;
2928

3029
@Override
3130
protected Event doExecute(final RequestContext context) {
32-
OsfUrlProperties osfUrl = Optional.of(context).map(requestContext
33-
-> (OsfUrlProperties) requestContext.getFlowScope().get(OSF_URL_FLOW_PARAMETER)).orElse(null);
31+
final OsfUrlProperties osfUrl = Optional.of(context).map(
32+
requestContext -> (OsfUrlProperties) requestContext.getFlowScope().get(OsfCasWebflowConstants.FLOW_PARAMETER_OSF_URL)
33+
).orElse(null);
3434
if (osfUrl == null) {
35-
context.getFlowScope().put(OSF_URL_FLOW_PARAMETER, osfUrlProperties);
35+
context.getFlowScope().put(OsfCasWebflowConstants.FLOW_PARAMETER_OSF_URL, osfUrlProperties);
3636
}
3737
return success();
3838
}

src/main/java/io/cos/cas/osf/web/flow/support/OsfCasWebflowConstants.java

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,35 +2,45 @@
22

33
/**
44
* This is {@link OsfCasWebflowConstants}, which expands the default {@link org.apereo.cas.web.flow.CasWebflowConstants}
5-
* interface by adding OSF CAS customized action, state and view IDs.
5+
* interface by adding OSF CAS customized action, state, transition and view IDs as well as names web flow parameters.
66
*
77
* @author Longze Chen
88
* @since 20.0.0
99
*/
1010

1111
public interface OsfCasWebflowConstants {
1212

13-
String ACTION_ID_OSF_PRE_INITIAL_FLOW_SETUP = "osfCasPreInitialFlowSetupAction";
13+
String FLOW_PARAMETER_OSF_URL = "osfUrl";
1414

15-
String ACTION_ID_OSF_DEFAULT_LOGIN_CHECK = "osfDefaultLoginCheckAction";
15+
String ACTION_ID_OSF_PRE_INITIAL_FLOW_SETUP = "osfCasPreInitialFlowSetupAction";
1616

17-
String STATE_ID_OSF_DEFAULT_LOGIN_CHECK = "osfDefaultLoginCheck";
17+
String ACTION_ID_OSF_NON_INTERACTIVE_AUTHENTICATION_CHECK = "osfNonInteractiveAuthenticationCheckAction";
1818

19-
String TRANSITION_ID_USERNAME_PASSWORD_LOGIN = "continueToUsernamePasswordLogin";
19+
String ACTION_ID_OSF_DEFAULT_LOGIN_CHECK = "osfDefaultLoginCheckAction";
2020

2121
String ACTION_ID_OSF_INSTITUTION_LOGIN_CHECK = "osfInstitutionLoginCheckAction";
2222

23-
String STATE_ID_OSF_INSTITUTION_LOGIN_CHECK = "osfInstitutionLoginCheck";
23+
String TRANSITION_ID_USERNAME_PASSWORD_LOGIN = "continueToUsernamePasswordLogin";
2424

2525
String TRANSITION_ID_INSTITUTION_LOGIN = "switchToInstitutionLogin";
2626

2727
String TRANSITION_ID_ORCID_LOGIN_AUTO_REDIRECT = "autoRedirectToOrcidLogin";
2828

29+
String TRANSITION_ID_DEFAULT_SERVICE_LOGIN_AUTO_REDIRECT = "autoRedirectToDefaultServiceLogin";
30+
31+
String STATE_ID_OSF_NON_INTERACTIVE_AUTHENTICATION_CHECK = "osfNonInteractiveAuthenticationCheck";
32+
33+
String STATE_ID_OSF_DEFAULT_LOGIN_CHECK = "osfDefaultLoginCheck";
34+
35+
String STATE_ID_OSF_INSTITUTION_LOGIN_CHECK = "osfInstitutionLoginCheck";
36+
37+
String VIEW_ID_INSTITUTION_SSO_INIT = "casInstitutionLoginView";
38+
2939
String VIEW_ID_ORCID_LOGIN_AUTO_REDIRECT = "casAutoRedirectToOrcidLoginView";
3040

31-
String ACTION_ID_OSF_NON_INTERACTIVE_AUTHENTICATION_CHECK = "osfNonInteractiveAuthenticationCheckAction";
41+
String VIEW_ID_DEFAULT_SERVICE_LOGIN_AUTO_REDIRECT = "casAutoRedirectToDefaultServiceLoginView";
3242

33-
String STATE_ID_OSF_NON_INTERACTIVE_AUTHENTICATION_CHECK = "osfNonInteractiveAuthenticationCheck";
43+
String VIEW_ID_ONE_TIME_PASSWORD_REQUIRED = "casTwoFactorLoginView";
3444

3545
String VIEW_ID_ACCOUNT_NOT_CONFIRMED_OSF = "casAccountNotConfirmedOsfView";
3646

@@ -40,9 +50,5 @@ public interface OsfCasWebflowConstants {
4050

4151
String VIEW_ID_INVALID_VERIFICATION_KEY = "casInvalidVerificationKeyView";
4252

43-
String VIEW_ID_ONE_TIME_PASSWORD_REQUIRED = "casTwoFactorLoginView";
44-
45-
String VIEW_ID_INSTITUTION_SSO_INIT = "casInstitutionLoginView";
46-
4753
String VIEW_ID_INSTITUTION_SSO_FAILED = "casInstitutionSsoFailedView";
4854
}

src/main/java/io/cos/cas/osf/web/support/OsfCasLoginContext.java

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,13 @@ public class OsfCasLoginContext implements Serializable {
2626

2727
private static final long serialVersionUID = 7523144720609509742L;
2828

29-
private String serviceUrl;
29+
/**
30+
* The encoded service URL provided by the "service=" query param in the request URL.
31+
*
32+
* This attribute is deprecated and should be removed since 1) ThymeLeaf handles URL building elegantly in the template and 2) both of
33+
* the flow parameters "service.originalUrl" and "originalUrl" stores the current service information.
34+
*/
35+
private String encodedServiceUrl;
3036

3137
private String handleErrorName;
3238

@@ -38,18 +44,31 @@ public class OsfCasLoginContext implements Serializable {
3844

3945
private String orcidLoginUrl;
4046

47+
private boolean defaultService;
48+
49+
/**
50+
* The default service URL that uses OSF login endpoint with OSF home as destination.
51+
*
52+
* e.g. http(s)://[OSF Domain]/login?next=[encoded version of http(s)://[OSF Domain]/]
53+
*/
54+
private String defaultServiceUrl;
55+
4156
public OsfCasLoginContext (
42-
final String serviceUrl,
57+
final String encodedServiceUrl,
4358
final boolean institutionLogin,
4459
final String institutionId,
4560
final boolean orcidRedirect,
46-
final String orcidLoginUrl
61+
final String orcidLoginUrl,
62+
final boolean defaultService,
63+
final String defaultServiceUrl
4764
) {
48-
this.serviceUrl = serviceUrl;
65+
this.encodedServiceUrl = encodedServiceUrl;
4966
this.handleErrorName = null;
5067
this.institutionLogin = institutionLogin;
5168
this.institutionId = institutionId;
5269
this.orcidRedirect = orcidRedirect;
5370
this.orcidLoginUrl = orcidLoginUrl;
71+
this.defaultService = defaultService;
72+
this.defaultServiceUrl = defaultServiceUrl;
5473
}
5574
}

src/main/resources/messages.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -545,6 +545,7 @@ screen.pm.button.backtoosf=Back to OSF
545545
screen.delegation.button.orcid=Sign in with ORCiD
546546
screen.delegation.button.institution=Sign in through institution
547547
screen.delegation.heading.orcidredirect=Redirecting to ORCiD
548+
screen.flowless.heading.defaultserviceredirect=Redirecting to OSF login
548549
#
549550
# Two factor and login form submission
550551
#
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head th:with="defaultServiceLoginUrl=@{/login(service=${osfCasLoginContext.defaultServiceUrl})}">
4+
<!-- When this template is rendered, both ${osfCasLoginContext.defaultSerivceUrl}
5+
and #{screen.flowless.heading.defaultserviceredirect} are guranteed to exist. -->
6+
<meta http-equiv="refresh" th:content="${'0; url=' + defaultServiceLoginUrl}" />
7+
<title th:text="#{screen.flowless.heading.defaultserviceredirect}"></title>
8+
</head>
9+
</html>

0 commit comments

Comments
 (0)