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
|