1+ package com .onelogin .saml2 .authn ;
2+
3+ import java .net .URL ;
4+
5+ import com .onelogin .saml2 .model .AssertionConsumerService ;
6+ import com .onelogin .saml2 .settings .Saml2Settings ;
7+
8+ /**
9+ * Interfaced used to select the Assertion Consumer Service (ACS) to be
10+ * specified in an authentication request. An instance of this interface can be
11+ * passed as an input parameter in a {@link AuthnRequestParams} to be used when
12+ * initiating a login operation.
13+ * <p>
14+ * A set of predefined implementations are provided: they should cover the most
15+ * common cases.
16+ */
17+ @ FunctionalInterface
18+ public interface AssertionConsumerServiceSelector {
19+
20+ /**
21+ * Simple class holding data used to select an Assertion Consumer Service (ACS)
22+ * within an authentication request.
23+ * <p>
24+ * The index, if specified, has priority over the pair URL/protocol binding.
25+ */
26+ static class AssertionConsumerServiceSelection {
27+ /** Assertion Consumer Service index. */
28+ public final Integer index ;
29+ /** Assertion Consumer Service URL. */
30+ public final URL url ;
31+ /** Assertion Consumer Service protocol binding. */
32+ public final String protocolBinding ;
33+
34+ /**
35+ * Creates an Assertion Consumer Service selection by index.
36+ *
37+ * @param index
38+ * the ACS index
39+ */
40+ public AssertionConsumerServiceSelection (final int index ) {
41+ this .index = index ;
42+ this .url = null ;
43+ this .protocolBinding = null ;
44+ }
45+
46+ /**
47+ * Creates an Assertion Consumer Service selection by URL and protocol binding.
48+ *
49+ * @param url
50+ * the ACS URL
51+ * @param protocolBinding
52+ * the ACS protocol binding
53+ */
54+ public AssertionConsumerServiceSelection (final URL url , final String protocolBinding ) {
55+ this .index = null ;
56+ this .url = url ;
57+ this .protocolBinding = protocolBinding ;
58+ }
59+ }
60+
61+ /**
62+ * @return a selector that will cause the authentication request not to specify
63+ * any Assertion Consumer Service, letting the IdP determine which is
64+ * the default one; if the agreement between the SP and the IdP to map
65+ * Assertion Consumer Services is based on metadata, it means that the
66+ * IdP is expected to select the ACS marked there as being the default
67+ * one (or the only declared ACS, if just one exists and hopefully not
68+ * explicitly set as <strong>not</strong> being the default one...);
69+ * indeed, in sane cases the final selection result is expected to be
70+ * the same the one provided by
71+ * {@link AssertionConsumerServiceSelector#useDefaultByIndex(Saml2Settings)}
72+ * and
73+ * {@link AssertionConsumerServiceSelector#useDefaultByUrlAndBinding(Saml2Settings)},
74+ * with those two however causing an explicit indication of the choice
75+ * being made by the SP in the authentication request, indication that
76+ * the IdP must then respect
77+ */
78+ static AssertionConsumerServiceSelector useImplicitDefault () {
79+ return () -> null ;
80+ }
81+
82+ /**
83+ * @param settings
84+ * the SAML settings, containing the list of the available
85+ * Assertion Consumer Services (see
86+ * {@link Saml2Settings#getSpAssertionConsumerServices()})
87+ * @return a selector that will cause the authentication request to explicitly
88+ * specify the default Assertion Consumer Service declared in a set of
89+ * SAML settings, selecting it by index; if no default ACS could be
90+ * unambiguously detected, this falls back to
91+ * {@link #useImplicitDefault()}
92+ * @see Saml2Settings#getSpAssertionConsumerServices()
93+ * @see Saml2Settings#getSpDefaultAssertionConsumerService()
94+ */
95+ static AssertionConsumerServiceSelector useDefaultByIndex (final Saml2Settings settings ) {
96+ return settings .getSpDefaultAssertionConsumerService ().map (AssertionConsumerServiceSelector ::byIndex )
97+ .orElse (useImplicitDefault ());
98+ }
99+
100+ /**
101+ * @param settings
102+ * the SAML settings, containing the list of the available
103+ * Assertion Consumer Services (see
104+ * {@link Saml2Settings#getSpAssertionConsumerServices()})
105+ * @return a selector that will cause the authentication request to explicitly
106+ * specify the default Assertion Consumer Service declared in a set of
107+ * SAML settings, selecting it by URL and protocol binding; if no
108+ * default ACS could be unambiguously detected, this falls back to
109+ * {@link #useImplicitDefault()}
110+ * @see Saml2Settings#getSpAssertionConsumerServices()
111+ * @see Saml2Settings#getSpDefaultAssertionConsumerService()
112+ */
113+ static AssertionConsumerServiceSelector useDefaultByUrlAndBinding (final Saml2Settings settings ) {
114+ return settings .getSpDefaultAssertionConsumerService ().map (AssertionConsumerServiceSelector ::byUrlAndBinding )
115+ .orElse (useImplicitDefault ());
116+ }
117+
118+ /**
119+ * @param assertionConsumerService
120+ * the Assertion Consumer Service to select
121+ * @return a selector that chooses the specified Assertion Consumer Service by
122+ * index
123+ */
124+ static AssertionConsumerServiceSelector byIndex (final AssertionConsumerService assertionConsumerService ) {
125+ return byIndex (assertionConsumerService .getIndex ());
126+ }
127+
128+ /**
129+ * @param assertionConsumerService
130+ * the Assertion Consumer Service to select
131+ * @return a selector that chooses the specified Assertion Consumer Service by
132+ * location URL and protocol binding
133+ */
134+ static AssertionConsumerServiceSelector byUrlAndBinding (final AssertionConsumerService assertionConsumerService ) {
135+ return () -> new AssertionConsumerServiceSelection (assertionConsumerService .getLocation (),
136+ assertionConsumerService .getBinding ());
137+ }
138+
139+ /**
140+ * @param index
141+ * the index of the Assertion Consumer Service to select
142+ * @return a selector that chooses the Assertion Consumer Service with the given
143+ * index
144+ */
145+ static AssertionConsumerServiceSelector byIndex (final int index ) {
146+ return () -> new AssertionConsumerServiceSelection (index );
147+ }
148+
149+ /**
150+ * @param url
151+ * the URL of the Assertion Consumer Service to select
152+ * @param protocolBinding
153+ * the protocol binding of the Assertion Consumer Service to select
154+ * @return a selector that chooses the Assertion Consumer Service with the given
155+ * URL and protocol binding
156+ */
157+ static AssertionConsumerServiceSelector byUrlAndBinding (final URL url , final String protocolBinding ) {
158+ return () -> new AssertionConsumerServiceSelection (url , protocolBinding );
159+ }
160+
161+ /**
162+ * Returns a description of the selected Assertion Consumer Service.
163+ *
164+ * @return the service index, or <code>null</code> if the default one should be
165+ * selected
166+ */
167+ AssertionConsumerServiceSelection getAssertionConsumerServiceSelection ();
168+ }
0 commit comments