~ubuntu-branches/ubuntu/gutsy/lasso/gutsy

« back to all changes in this revision

Viewing changes to docs/lasso-book/writing-a-c-sp.txt

  • Committer: Bazaar Package Importer
  • Author(s): Frederic Peters
  • Date: 2004-09-13 09:26:34 UTC
  • Revision ID: james.westby@ubuntu.com-20040913092634-01vdfl8j9cp94exa
Tags: upstream-0.4.1
ImportĀ upstreamĀ versionĀ 0.4.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
=======================================
 
2
Writing a Liberty service provider in C
 
3
=======================================
 
4
 
 
5
:Author: Frederic Peters
 
6
:Contact: fpeters@entrouvert.com
 
7
:date: $Date: 2004/09/04 09:04:19 $
 
8
:revision: $Revision: 1.35 $
 
9
:copyright: Copyright Ā© 2004 Entr'ouvert
 
10
 
 
11
.. contents:: Table of Contents
 
12
.. section-numbering::
 
13
 
 
14
 
 
15
Lasso Projects Basics
 
16
=====================
 
17
 
 
18
Lasso functions are defined in several header files typically located in
 
19
``/usr/include/lasso/`` or ``/usr/local/include/lasso/``.  It is possible to
 
20
include individual files but in most case it is enough to include the main
 
21
``lasso.h``.
 
22
 
 
23
The first thing to do is then to call ``lasso_init()``.  Similarly the last
 
24
thing will be to call ``lasso_shutdown()``.  The smallest and useless Lasso
 
25
project will therefore be::
 
26
 
 
27
  #include <lasso/lasso.h>
 
28
 
 
29
  int main(int argc, char *argv[])
 
30
  {
 
31
      lasso_init();
 
32
      printf("Hello world.\n");
 
33
      lasso_shutdown();
 
34
      return 0;
 
35
  }
 
36
 
 
37
Lasso uses a tool called ``pkg-config`` to know the necessary flags for
 
38
compilation and linking.
 
39
 
 
40
::
 
41
 
 
42
  $ pkg-config lasso --cflags
 
43
 -DXMLSEC_CRYPTO=\"openssl\" -DXMLSEC_LIBXML_260=1 -D__XMLSEC_FUNCTION__=__FUNCTION__
 
44
 -DXMLSEC_NO_XKMS=1 -DXMLSEC_NO_CRYPTO_DYNAMIC_LOADING=1 -DXMLSEC_CRYPTO_OPENSSL=1
 
45
 -I/usr/include/lasso -I/usr/include/libxml2 -I/usr/include/xmlsec1 -I/usr/include/glib-2.0
 
46
 -I/usr/lib/glib-2.0/include
 
47
  $ pkg-config lasso --libs
 
48
 -llasso -lxmlsec1-openssl -lxmlsec1 -lssl -lcrypto -ldl -lgobject-2.0 -lxslt -lxml2
 
49
 -lpthread -lz -lm -lglib-2.0
 
50
 
 
51
 
 
52
Creating an executable from the previous sample would then a simple matter of
 
53
calling ``gcc`` with the right flags.  But there is currently a bug in
 
54
XMLSec, the library used by Lasso to provide XML Signature and XML Encryption
 
55
support.  It is possible to workaround the bug::
 
56
 
 
57
  $ gcc hello.c -o hello $(pkg-config lasso --cflags --libs)
 
58
 <command line>:4:16: missing terminating " character
 
59
  $ gcc hello.c -o hello $(pkg-config xmlsec1 --cflags --libs | tr -d '\\')
 
60
  $ ./hello
 
61
 Hello world.
 
62
 
 
63
 
 
64
Liberty and Lasso profiles
 
65
==========================
 
66
 
 
67
Lasso provides the necessary functions to implement Liberty Alliance profiles,
 
68
as defined in the `Liberty ID-FF Bindings and Profiles Specification`_.  They
 
69
are:
 
70
 
 
71
- Single Sign-On and Federation
 
72
- Name Registration
 
73
- Federation Termination Notification
 
74
- Single Logout
 
75
- Identity Provider Introduction
 
76
- Name Identifier Mapping
 
77
- Name Identifier Encryption
 
78
 
 
79
Each profile maps to a Lasso object such as ``LassoLogin``, ``LassoLogout``...
 
80
Those are initialized with data known about identity and service providers,
 
81
available in a ``LassoServer`` object.
 
82
 
 
83
The ``LassoServer`` object may be created as follows:
 
84
 
 
85
::
 
86
 
 
87
  LassoServer *server;
 
88
  server = lasso_server_new("sp-metadata.xml",
 
89
                NULL, "sp-private-key.pem", "sp-crt.pem", lassoSignatureMethodRsaSha1);
 
90
  lasso_server_add_provider(server, "idp-metadata.xml",
 
91
                "idp-public-key.pem", "ca-crt.pem");
 
92
 
 
93
- ``sp-metadata.xml`` is the Liberty metadata file for the service provider
 
94
- ``idp-metadata.xml`` is the Liberty metadata file for the identity provider
 
95
- ``sp-private-key.pem`` is the service provider private key; used to sign
 
96
  documents
 
97
- ``sp-crt.pem`` is the service provider certificate; sent inside signed
 
98
  documents
 
99
- ``idp-public-key.pem`` is the identity provider public key; used to verify
 
100
  signature in documents sent by the identity provider
 
101
- ``ca-crt.pem`` is the certificate of the certification authority used by the
 
102
  identity provider.
 
103
 
 
104
It is of course possible to have several calls so ``lasso_server_add_provider``
 
105
if there are more than one identity provider.
 
106
 
 
107
.. note:: Figures in the previously referred Binding and Profiles specification
 
108
          document are quite helpful in figuring out the message passing.
 
109
 
 
110
 
 
111
Serialization
 
112
-------------
 
113
 
 
114
``LassoServer`` objects can be serialized into XML files::
 
115
 
 
116
  gchar *dump;
 
117
  FILE *fd;
 
118
 
 
119
  dump = lasso_server_dump(server);
 
120
  /* write dump into a file, a database, whatever */
 
121
  g_free(dump);
 
122
 
 
123
.. note:: ``lasso_server_dump`` (and other Lasso dump functions) allocates
 
124
          memory through GLib.  ``g_free`` is then the function to use instead
 
125
          of ``free`` to release memory.
 
126
 
 
127
It is then really easy to get back properly constructed objects::
 
128
 
 
129
  LassoServer *server;
 
130
  gchar *dump;
 
131
 
 
132
  /* restore dump from file, database, whatever */
 
133
  server = lasso_server_new_from_dump(dump);
 
134
 
 
135
.. warning:: The server dump only contains the filenames; not the actual file
 
136
             contents.  Files should not be moved afterwards.
 
137
 
 
138
 
 
139
 
 
140
Liberty Metadata Files
 
141
======================
 
142
 
 
143
 
 
144
They are descriptions of a provider containing ``providerID`` and various
 
145
norminative URLs::
 
146
 
 
147
  <?xml version="1.0"?>
 
148
  <EntityDescriptor
 
149
      providerID="https://sp.example.com/" xmlns="urn:liberty:metadata:2003-08">
 
150
    <SPDescriptor>
 
151
      <SingleLogoutServiceURL>https://sp.example.com/singleLogout</SingleLogoutServiceURL>
 
152
      <SingleLogoutProtocolProfile>http://projectliberty.org/profiles/slo-idp-soap</SingleLogoutProtocolProfile>
 
153
      <SoapEndpoint>https://sp.example.com/soapEndpoint</SoapEndpoint>
 
154
      <AssertionConsumerServiceURL id="AssertionConsumerServiceURL1" isDefault="true">
 
155
        https://sp.example.com/assertionConsumer
 
156
      </AssertionConsumerServiceURL>
 
157
      <AuthnRequestsSigned>true</AuthnRequestsSigned>
 
158
    </SPDescriptor>
 
159
  </EntityDescriptor>
 
160
 
 
161
Describe a service provider (with providerID ``https://sp.example.com``) whose
 
162
single logout service URL is ``https://sp.example.com/singleLogout``.  Refer to
 
163
the Liberty Alliance specifications for details.
 
164
 
 
165
 
 
166
Single Sign-On and Federation Profile
 
167
=====================================
 
168
 
 
169
.. warning:: The source code presented in this section has for sole purpose
 
170
             to explain the different steps necessary to implement this
 
171
             profile; they notably lack proper error checking.  See `Proper
 
172
             Error Checking`_ for details on error checking.
 
173
 
 
174
 
 
175
As a first step the user points its browser to the service provider to the
 
176
login URL; the service provider must then respond with an HTTP 302 Redirect
 
177
response, pointing the user browser to the identity provider single sign on
 
178
service.
 
179
 
 
180
.. note:: the login URL is not normative; any name will do.
 
181
 
 
182
 
 
183
``server`` is a ``LassoServer`` as seen earlier and ``idpProviderId`` is a
 
184
string with the identity provider Id (the string must match a providerID
 
185
defined in the metadata file).
 
186
 
 
187
::
 
188
 
 
189
  LassoLogin *login;
 
190
  
 
191
  login = lasso_login_new(server);
 
192
  lasso_login_init_authn_request(login, lassoHttpMethodRedirect);
 
193
  
 
194
  lasso_lib_authn_request_set_forceAuthn(
 
195
      LASSO_LIB_AUTHN_REQUEST(LASSO_PROFILE(login)->request), 1);
 
196
  lasso_lib_authn_request_set_isPassive(
 
197
      LASSO_LIB_AUTHN_REQUEST(LASSO_PROFILE(login)->request), 0);
 
198
  lasso_lib_authn_request_set_nameIDPolicy(
 
199
      LASSO_LIB_AUTHN_REQUEST(LASSO_PROFILE(login)->request), lassoLibNameIDPolicyTypeFederated);
 
200
  lasso_lib_authn_request_set_consent(
 
201
      LASSO_LIB_AUTHN_REQUEST(LASSO_PROFILE(login)->request), lassoLibConsentObtained);
 
202
  lasso_login_build_authn_request_msg(login, idpProviderId);
 
203
 
 
204
 
 
205
You can now redirect the user to the URL defined in ``LASSO_PROFILE(login)->msg_url``; for
 
206
example, in a CGI::
 
207
  
 
208
  printf("Location: %s\n", LASSO_PROFILE(login)->msg_url);
 
209
 
 
210
 
 
211
The user then logs in on the identity provider which ultimately redirects back
 
212
to the service provider; to the assertion consumer URL.  A SAML artifact is
 
213
passed in the query parameter.
 
214
 
 
215
.. note:: the assertion consumer URL is defined by Liberty; it must be declared
 
216
   in the ``AssertionConsumerServiceURL`` element of the metadata file.
 
217
 
 
218
::
 
219
 
 
220
  LassoLogin *login;
 
221
  
 
222
  login = lasso_login_new(server);
 
223
  lasso_login_init_request(login, query_string, lassoHttpMethodRedirect);
 
224
  lasso_login_build_request_msg(login);
 
225
 
 
226
The service provider must check this artifact using a SOAP request to the
 
227
identity provider.  The URL is ``LASSO_PROFILE(login)->msg_url`` while the
 
228
request is ``LASSO_PROFILE(login)->msg_body``.  The request must succeed with
 
229
an HTTP 200 status code; let's consider its content is put in the ``answer``,
 
230
the next statement would be::
 
231
 
 
232
  lasso_login_process_response_msg(login, answer);
 
233
 
 
234
The users are defined by a ``nameIdentifier`` (accessible through
 
235
``LASSO_PROFILE(login)->nameIdentifier``).  Those typically map to users
 
236
and sessions in some database on the service provider.  If existing; the
 
237
session should probably contains a ``session_dump`` element and the user a
 
238
``identity_dump`` element.  See `Database Considerations`_ below for more
 
239
informations.
 
240
 
 
241
It is now time to get them out of the database and apply them to the ``login``
 
242
object.
 
243
 
 
244
::
 
245
 
 
246
  if (session_dump != NULL) {
 
247
      lasso_profile_set_session_from_dump(LASSO_PROFILE(login), session_dump);
 
248
  }
 
249
  if (identity_dump != NULL) {
 
250
      lasso_profile_set_identity_from_dump(LASSO_PROFILE(login), identity_dump);
 
251
  }
 
252
  lasso_login_accept_sso(login);
 
253
 
 
254
After ``lasso_login_accept_sso`` the session and the identity are updated (or
 
255
created) and should then be saved.  If the identity has not regnogized by the
 
256
service provider an account will probably have to be created on the service
 
257
provider; this is a good opportunity to ask the user for more information.
 
258
 
 
259
You can get respective dumps like this::
 
260
 
 
261
  LassoIdentity *identity;
 
262
  LassoSession *session;
 
263
  char *identity_dump = NULL, *session_dump = NULL;
 
264
 
 
265
  if (lasso_profile_is_identity_dirty(LASSO_PROFILE(login))) {
 
266
      identity = lasso_profile_get_identity(LASSO_PROFILE(login));
 
267
      identity_dump = lasso_identity_dump(identity);
 
268
      lasso_identity_destroy(identity);
 
269
  }
 
270
 
 
271
  if (lasso_profile_is_session_dirty(LASSO_PROFILE(login))) {
 
272
      session = lasso_profile_get_session(LASSO_PROFILE(login));
 
273
      session_dump = lasso_session_dump(session);
 
274
      lasso_session_destroy(session);
 
275
  }
 
276
 
 
277
  /* code to store identity_dump and session_dump */
 
278
 
 
279
Finally the ``login`` object can then be destroyed::
 
280
 
 
281
  lasso_login_destroy(login);
 
282
 
 
283
And a success web page displayed.
 
284
 
 
285
 
 
286
Single Logout Profile
 
287
=====================
 
288
 
 
289
There are different single logout profiles; some initiated on the identity
 
290
provider, others initiated on the service provider, using either HTTP redirects
 
291
or SOAP requests.
 
292
 
 
293
This part is about a logout using SOAP and initiated on the service provider.
 
294
 
 
295
::
 
296
 
 
297
  LassoLogout *logout;
 
298
 
 
299
  logout = lasso_logout_new(lassoServer, lassoProviderTypeSp);
 
300
 
 
301
 
 
302
Identity and session dumps should be restored to prepare the logout request.
 
303
 
 
304
::
 
305
 
 
306
  if (session_dump != NULL) {
 
307
      lasso_profile_set_session_from_dump(LASSO_PROFILE(logout), session_dump);
 
308
  }
 
309
  if (identity_dump != NULL) {
 
310
      lasso_profile_set_identity_from_dump(LASSO_PROFILE(logout), identity_dump);
 
311
  }
 
312
  
 
313
  lasso_logout_init_request(logout, NULL, lassoHttpMethodSoap);
 
314
  lasso_logout_build_request_msg(logout);
 
315
 
 
316
 
 
317
The service provider must then make a SOAP request to the identity provider;
 
318
``msg_url`` and ``msg_body``.  You should then pass the answer to Lasso::
 
319
 
 
320
  lasso_logout_process_response_msg(logout, answer, lassoHttpMethodSoap)
 
321
 
 
322
And save back session and user dump; the process is similar as the one at the
 
323
end of the single sign on profile.
 
324
 
 
325
 
 
326
Proper Error Checking
 
327
=====================
 
328
 
 
329
Most Lasso functions returns 0 on success and a negative number on failure.  It
 
330
is strongly advised to check this return code on each call.
 
331
 
 
332
::
 
333
 
 
334
  int rc;
 
335
 
 
336
  rc = lasso_logout_process_response_msg(logout, answer, lassoHttpMethodSoap)
 
337
  if (rc) {
 
338
      fprintf(stderr, "Lasso Error: %d\n", rc);
 
339
      /* handling error; most probably bailing out */
 
340
  }
 
341
 
 
342
 
 
343
Database Considerations
 
344
=======================
 
345
 
 
346
Lasso has been designed to let the service provider keep on using existing
 
347
databases.  Typically there is already a table describing users; just add an
 
348
identity dump column to the existing table:
 
349
 
 
350
=======    ========================================    ==============
 
351
User Id    existing data (name, address...)            Identity dump
 
352
=======    ========================================    ==============
 
353
1          ...                                         <Identity> ...
 
354
2          ...                                         <Identity> ...
 
355
=======    ========================================    ==============
 
356
 
 
357
Mapping between existing users and name identifiers sent by the identity
 
358
provider can be done with a simple table.
 
359
 
 
360
===============    =======
 
361
Name Identifier    User Id
 
362
===============    =======
 
363
AQWWRRS...         1
 
364
CGFASDE...         2
 
365
YYSSSDS...         1
 
366
===============    =======
 
367
 
 
368
.. note:: A separate table is needed because one user Id could map
 
369
          to several name identifiers; in case there are several identity
 
370
          providers.
 
371
 
 
372
Sessions are also commonly stored in databases; just add a session dump column
 
373
to the existing session table:
 
374
 
 
375
==========    =================    =============
 
376
Session Id    misc session data    Session dump
 
377
==========    =================    =============
 
378
6744066       ...                  <Session> ...
 
379
3338824       ...                  <Session> ...
 
380
==========    =================    =============
 
381
 
 
382
Likewise sessions should be mapped to name identifiers.
 
383
 
 
384
===============    ==========
 
385
Name Identifier    Session Id
 
386
===============    ==========
 
387
AQWWRRS...         3338824
 
388
===============    ==========
 
389
 
 
390
 
 
391
 
 
392
API Reference
 
393
=============
 
394
 
 
395
- LassoLogin_
 
396
- LassoLogout_
 
397
- LassoIdentity_
 
398
- LassoServer_
 
399
- LassoSession_
 
400
 
 
401
 
 
402
 
 
403
 
 
404
.. _Liberty ID-FF Bindings and Profiles Specification:
 
405
   http://www.projectliberty.org/specs/draft-liberty-idff-bindings-profiles-1.2-errata-v1.0.pdf
 
406
 
 
407
.. _LassoLogin: /lasso-api/lassologin.html
 
408
.. _LassoLogout: /lasso-api/lassologout.html
 
409
.. _LassoIdentity: /lasso-api/lassoidentity.html
 
410
.. _LassoServer: /lasso-api/lassoserver.html
 
411
.. _LassoSession: /lasso-api/lassosession.html
 
412