summaryrefslogtreecommitdiffstats
path: root/docs/lasso-book/single-sign-on.process
blob: d078a4ccb53dcc8a5c130bb7f0bcd225489d3057 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
Single Sign-On and Federation
    SP
        /login (* url not normative *)
            login = lasso_login_new(server)
            lasso_login_init_authn_request(login, idpProviderId, method)
                # method is one of:
                #  - LASSO_HTTP_METHOD_REDIRECT
                #  - LASSO_HTTP_METHOD_POST

            request = LASSO_LIB_AUTHN_REQUEST(LASSO_PROFILE(login)->request)

            request->NameIDPolicy = strdup(policy)
                # policy is one of:
                #  - LASSO_LIB_NAMEID_POLICY_TYPE_FEDERATED (for SSO and federation)
                #  - LASSO_LIB_NAMEID_POLICY_TYPE_NONE (for SSO only)
                #  - LASSO_LIB_NAMEID_POLICY_TYPE_ONE_TIME (anonymous SSO)
                #  - LASSO_LIB_NAMEID_POLICY_TYPE_ANY (Tries FEDERATED otherwise ONE_TIME)
            request->ForceAuthn = TRUE;
            request->IsPassive = FALSE;
            request->ProtocolProfile = strdup(protocol_profile);
                # protocol_profile is one of:
                #  - LASSO_LIB_PROTOCOL_PROFILE_BRWS_ART;
                #  - LASSO_LIB_PROTOCOL_PROFILE_BRWS_POST;
            request->consent = strdup(consent);
                # consent is one of:
                #  - LASSO_LIB_CONSENT_OBTAINED
                #  - LASSO_LIB_CONSENT_OBTAINED_PRIOR
                #  - LASSO_LIB_CONSENT_OBTAINED_CURRENT_IMPLICIT
                #  - LASSO_LIB_CONSENT_OBTAINED_CURRENT_EXPLICIT
                #  - LASSO_LIB_CONSENT_UNAVAILABLE
                #  - LASSO_LIB_CONSENT_INAPPLICABLE

            lasso_login_build_authn_request_msg(login)
            
            IF method == REDIRECT
                REDIRECT TO LASSO_PROFILE(login)->msg_url
            
            IF method == POST
                DISPLAY HTML FORM
                   <body onload="document.forms[0].submit()">
                    <form action="** LASSO_PROFILE(login)->msg_url **" method="post">
                     <input type="hidden" name="LAREQ"
                       value="** LASSO_PROFILE(login)->msg_body **"/>
                    </form>
                   </body>


    IdP
        /singleSignOn (* normative, Single Sign On service URL *)
            login = lasso_login_new(server)
            lasso_profile_set_identity_from_dump(LASSO_PROFILE(login), identity_dump)
            lasso_profile_set_session_from_dump(LASSO_PROFILE(login), session_dump)
            IF METHOD IS GET
                IF lasso_profile_is_liberty_query(/query string/)
                    authn_request_msg = /query string/
                ELSE
                   # The single sign-on service URL has been accessed directly by the user, so
                   # proceed to an IDP initiated SSO.
                   # First ask the user the SP for which he wants to proceed to sign-on.
                   lasso_login_init_idp_initiated_authn_request(serviceProviderId)
            ELSE (METHOD IS POST)
                authn_request_msg = /form submitted LAREQ field/

            IF authn_request_msg:
                lasso_login_process_authn_request_msg(login, authn_request_msg)

            IF lasso_login_must_authenticate(login)
                # proceed to authentication
                # may serialize login object now: lasso_login_dump(login)  

                # (...)

                # may be coming back from another function; another url
                # unserialize with lasso_login_new_from_dump(dump)
                userAuthenticated = TRUE # or FALSE if authentication failed
            ELSE
                userAuthenticated = TRUE
                    # or FALSE if it was not authenticated previously

            consentObtained = FALSE
            IF userAuthenticated
                IF lasso_login_must_ask_for_consent(login)
                   # ask user if he consents to federation
                   # may serialize login object now: lasso_login_dump(login)  

                   # (...)

                   # may be coming back from another function; another url
                   # unserialize with lasso_login_new_from_dump(dump)
                   consentObtained = TRUE # or FALSE if user didn't give its consent

            IF lasso_login_validate_request_msg(login, userAuthenticated, consentObtained) == 0:
                # build and fill assertion
                lasso_login_build_assertion(login, authenticationMethod,
                        authenticationInstant, reauthenticationTime
                        assertionIsNotBefore, assertionIsNotOnOrAfter)
                # any other change to the assertion can take place here

            IF login->protocolProfile IS LASSO_LOGIN_PROTOCOL_PROFILE_BRWS_ART
                lasso_login_build_artifact_msg(login, LASSO_HTTP_METHOD_REDIRECT)
            ELSE # IF login->protocolProfile IS lassoLoginProtocolProfileBrwsPost
                lasso_login_build_authn_response_msg(login)

            # map LASSO_PROFILE(login)->nameIdentifier to user and session
            # (write this down in a database)

            IF lasso_profile_is_identity_dirty(LASSO_PROFILE(login))
                identity = lasso_profile_get_identity(LASSO_PROFILE(login))
                # save identity;
                #   serialization with lasso_identity_dump(identity)

            IF lasso_profile_is_session_dirty(LASSO_PROFILE(login))
                session = lasso_profile_get_session(LASSO_PROFILE(login))
                # save session;
                #   serialization with lasso_session_dump(session)

            IF login->protocolProfile IS lassoLoginProtocolProfileBrwsArt
                # map assertionArtifact to login.remote_providerID and web session
                # FIXME : artifact can be either Redirect or POST
                REDIRECT TO LASSO_PROFILE(login)->msg_url

            ELSE # IF login->protocolProfile IS lassoLoginProtocolProfileBrwsPost
                DISPLAY HTML FORM
                   <body onload="document.forms[0].submit()">
                    <form action="** LASSO_PROFILE(login)->msg_url **" method="post">
                     <input type="hidden" name="LARES"
                       value="** LASSO_PROFILE(login)->msg_body **"/>
                    </form>
                   </body>


    SP
        /assertionConsumer (* normative, assertion consumer service URL *)
            login = lasso_login_new(server)
            IF METHOD IS GET OR SUBMITTED FORM HAS LAREQ FIELD
                    IF METHOD IS GET
                        artifact_msg = /query string/
                        relayState = /query string, RelayState var/
                        method = LASSO_HTTP_METHOD_REDIRECT
                    ELSE # IF METHOD IS POST
                        artifact_msg = /form submitted LAREQ field/
                        relayState = /form submitted RelayState field/
                        method = LASSO_HTTP_METHOD_POST

                    lasso_login_init_request(login, artifact_msg, method)
                    lasso_login_build_request_msg(login)

                    SOAP CALL ---------------------------------------------------------\
                        TO LASSO_PROFILE(login)->msg_url                               |
                        BODY LASSO_PROFILE(login)->msg_body

                    lasso_login_process_response_msg(login, soap_answer_message)

            ELSE IF SUBMITTED FORM HAS LARES FIELD
                response_msg = /form submitted LARES field/
                lasso_login_process_authn_response_msg(login, response_msg)
                relayState = LASSO_PROFILE(login)->msg_RelayState

            nameIdentifier = LASSO_PROFILE(login)->nameIdentifier

            IF known nameIdentifier
                # GET BACK identity_dump and session_dump
                # First retrieve session and user by nameIdentifier
                lasso_profile_set_identity_from_dump(LASSO_PROFILE(login), identity_dump)
                lasso_profile_set_session_from_dump(LASSO_PROFILE(login), session_dump)

            lasso_login_accept_sso(login)
            
            IF lasso_profile_is_identity_dirty(LASSO_PROFILE(login))
                identity = lasso_profile_get_identity(LASSO_PROFILE(login))
                # save identity;
                #   serialization with lasso_identity_dump(identity)

            IF lasso_profile_is_session_dirty(LASSO_PROFILE(login))
                session = lasso_profile_get_session(LASSO_PROFILE(login))
                # save session;
                #   serialization with lasso_session_dump(session)

            IF nameIdentifier was not known:
                # if the user was not yet logged on SP before SSO, it is a good place to ask the
                # user to register on SP, to create a web session and store lasso_session_dump in
                # it, and to create or retrieve user account and store lasso_identity_dump there.
            
            REDIRECT anywhere # SSO is finished


    IdP                                                                                |
        /soapEndPoint (* normative, SOAP endpoint *)                              <----/
            soap_msg # is the received SOAP message body
            request_type = lasso_profile_get_request_type_from_soap_msg(soap_msg);

            IF request_type IS lassoRequestTypeLogin
                login = lasso_login_new(server);
                lasso_login_process_request_msg(login, soap_msg);
                # Retrieve remote_providerID and web session using login->assertionArtifact
                # and then remove them.
                # Retrieve session_dump stored in session.
                lasso_profile_set_session_from_dump(LASSO_PROFILE(login), session_dump)
                lasso_login_build_response_msg(login, remote_providerID)
                ANSWER SOAP REQUEST WITH: LASSO_PROFILE(login)->msg_body