| Lasso Reference Manual | ||||
|---|---|---|---|---|
| Top | Description | ||||
struct LassoEcp; LassoEcp * lasso_ecp_new (LassoServer *server); lasso_error_t lasso_ecp_process_authn_request_msg (LassoEcp *ecp,const char *authn_request_msg); lasso_error_t lasso_ecp_process_response_msg (LassoEcp *ecp,const char *response_msg); void lasso_ecp_destroy (LassoEcp *ecp);
# Introduction
The LassoEcp object is used to implement a SAMLv2 ECP client. If you want to support ECP in a SP see [ecp-sp]. If you want to support ECP in a IdP see [ecp-idp].
# ECP Operational Steps
SAML2 Profile for ECP (Section 4.2) defines these steps for an ECP transaction
1. ECP issues HTTP Request to SP 2. SP issues <samlp:AuthnRequest> to ECP using PAOS 3. ECP determines IdP 4. ECP conveys <samlp:AuthnRequest> to IdP using SOAP 5. IdP identifies principal 6. IdP issues <samlp:Response> to ECP, targeted at SP using SOAP 7. ECP conveys <samlp:Response> to SP using PAOS 8. SP grants or denies access to principal
LassoEcp * lasso_ecp_new (LassoServer *server);
Creates a new LassoEcp.
Returns : |
a newly created LassoEcp object; or NULL if an error occured |
lasso_error_t lasso_ecp_process_authn_request_msg (LassoEcp *ecp,const char *authn_request_msg);
This function implements the following ECP step: ECP Step 3, ECP determines IdP ECP Step 4, parse SP PAOS Authn request, build SOAP for IdP
This is to be used in an ECP client. The authn_request_msg is the
SOAP PAOS message received from the SP in response to a resource
request with an HTTP Accept header indicating PAOS support.
The following actions are implemented:
* Extract the samlp:AuthnRequest from the SOAP body and build a new SOAP message containing the samlp:AuthnRequest which will be forwarded to the IdP. This new SOAP message is stored in the LassoProfile.msg_body.
* Parse the SOAP header which will contain a paos:Request, a ecp:Request and optionally a ecp:RelayState. Some of the data in these headers need to be preserved for later processing steps.
1. The paos:Request.responseConsumerURL is copied to the LassoEcp.response_consumer_url. This is necessary because the ECP client MUST assure it matches the ecp:Response.AssertionConsumerServiceURL returned by the IdP to prevent man-in-the-middle attacks. It must also match the samlp:AuthnRequest.AssertionConsumerServiceURL.
2. If the paos:Request contained a messageID it is copied to LassoEcp.message_id so it can be returned in the subsequent paos:Response.refToMessageID. This allows a provider to correlate messages.
3. If an ecp:RelayState is present it is copied to LassoEcp.relaystate. This is necessary because in step 7 when the ECP responds to the SP it must include RelayState provided in the request.
* In addition the following items are copied to the LassoEcp for informational purposes:
* LassoEcp.issuer = ecp:Request.Issuer
* LassoEcp.provider_name = ecp:Request.ProviderName
* LassoEcp.is_passive = ecp:Request.IsPassive
* LassoEcp.sp_idp_list = ecp:Request.IDPList
# IdP Selection
In Step 3. The ECP must determine the IdP to forward the AuthnRequest to. There are two sets of IdP's which come into play. The ECP client has a set of IdP's it knows about because their metadata has been loaded into the LassoServer object. The SP may optionally send a list of IdP's in the ecp:Request that it trusts.
The selected IdP *must* be one of the IdP's loaded into the LassoServer object from metadata because the IdP endpoints must be known. Furthermore the IdP *must* support the SingleSignOnService using the SOAP binding. Therefore the known IdP's are filtered for those that match this criteria and a list of their EntityID's are assigned to LassoEcp.known_idp_entity_ids_supporting_ecp. The selected IdP *must* be a member of this list.
The SP may optionally send a list of IdP's it trusts. If the SP sends an IDPList the selected IdP should be a member of this list and from above we know it must also be a member of the LassoEcp.known_idp_entity_ids_supporting_ecp. Therefore the LassoEcp.known_sp_provided_idp_entries_supporting_ecp list is set to the common members (e.g. intersection) of the SP provided IdP list and the list of known IdP's supporting ECP.
When making an IdP selection if the SP provided an IdP List (use
LassoEcp.lasso_ecp_has_sp_idplist()) then it should be selected
from the LassoEcp.known_sp_provided_idp_entries_supporting_ecp
list. Otherwise the IdP should be selected from
LassoEcp.known_idp_entity_ids_supporting_ecp.
A default IdP will be selected using the above logic by picking the
first IdP in the appropriate list, it's endpoint URL will be
assigned to LassoProfile.msg_url. The above processing is
implemented by LassoEcp.lasso_ecp_process_sp_idp_list() and if the
SP IDPList is updated this routine should be called.
A note about the 3 IdP lists. The LassoEcp.sp_idp_list.IDPList and LassoEcp.known_sp_provided_idp_entries_supporting_ecp are GList's of LassoSamlp2IDPEntry object which have a ProviderID, Name, and Loc attribute. You may wish to use this SP provided information when making a decision or presenting in a user interface that allows a user to make a choice. The LassoEcp.known_idp_entity_ids_supporting_ecp is a GList of EntityID strings.
Given the EntityID of an IdP you can get the ECP endpoint by
calling LassoEcp.lasso_ecp_get_endpoint_url_by_entity_id()
# Results
After a successful return from this call you are ready to complete Step 4. and forward the request the IdP.
The URL to send to the request to will be LassoProfile.msg_url (if you accept the default IdP) and the body of the message to post will be LassoProfile.msg_body.
# Side Effects
After a successful return the LassoEcp object will be updated with:
* ecp->response_consumer_url = paos_request->responseConsumerURL * ecp->message_id = paos_request->messageID * ecp->relaystate = ecp_relaystate->RelayState * ecp->issuer = ecp_request->Issue * ecp->provider_name = ecp_request->ProviderName * ecp->is_passive = ecp_request->IsPassive * ecp->known_idp_entity_ids_supporting_ecp * ecp->sp_idp_list = ecp_request->IDPList * ecp->known_sp_provided_idp_entries_supporting_ecp
|
this LassoEcp object |
|
the PAOS authn request received from the SP |
lasso_error_t lasso_ecp_process_response_msg (LassoEcp *ecp,const char *response_msg);
The function implements ECP Step 7; parse IdP SOAP response and build PAOS response for SP.
See SAML Profile Section 4.2.4.5 PAOS Response Header Block: ECP to SP
This is to be used in an ECP client. The response_msg parameter
contains the SOAP response from the IdP. We extract the ECP Header
Block and body from it. We will generate a new PAOS message to send
to the SP, the SOAP header will contain a paos:Response. If we
received a paos:Request.MessageID in Step. 4 from the SP then we
will copy it back to the paos:Response.refToMessageID. If we
received a RelayState we will add that to the SOAP header as well.
To prevent a man-in-the-middle attack we verify the responseConsumerURL we received in Step 4 matches the ecp:Response.AssertionConsumerServiceURL we just received back from the IdP. If they do not match we return a LASSO_ECP_ERROR_ASSERTION_CONSUMER_URL_MISMATCH error and set the LassoProvider.msg_body to the appropriate SOAP fault.
The new PAOS message for the SP we are buiding contains the IdP response in the new SOAP body and the new SOAP headers will contain a paso:Response and optionally an ecp:RelayState.
After a successful return from this call you are ready to complete Step 7. and forward the response to the SP.
The PASO message is assigned to the LassoProvider.msg_body and the desination URL is assigned to the LassoProvider.msg_url.
# Side Effects
After a successful return the LassoEcp object will be updated with:
* ecp->assertion_consumer_url = ecp_response->AssertionConsumerServiceURL * ecp.profile.msg_url = ecp->assertion_consumer_url * ecp.profile.msg_body_url = PAOS response to SP
|
this LassoEcp object |
|
the SOAP response from the IdP |