LassoEcp: lasso Reference Manual

## LassoEcp LassoEcp — Enhanced Client or Proxy Profile (SAMLv2) |

## Functions

gboolean | lasso_ecp_is_provider_in_sp_idplist ()
gboolean | lasso_ecp_is_idp_entry_known_idp_supporting_ecp ()
void | lasso_ecp_set_known_sp_provided_idp_entries_supporting_ecp ()
gboolean | lasso_ecp_has_sp_idplist ()
gchar * | lasso_ecp_get_endpoint_url_by_entity_id ()
int | lasso_ecp_process_sp_idp_list ()
LassoEcp * | lasso_ecp_new ()
lasso_error_t | lasso_ecp_process_authn_request_msg ()
lasso_error_t | lasso_ecp_process_response_msg ()
void | lasso_ecp_destroy ()

## Types and Values

struct | LassoEcp

## Object Hierarchy

        GObject
        ╰── LassoNode
            ╰── LassoProfile
                ╰── LassoEcp

## Description

### 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

## Functions

### lasso_ecp_is_provider_in_sp_idplist ()

    gboolean
    lasso_ecp_is_provider_in_sp_idplist (LassoEcp *ecp,
                                         const gchar *entity_id);

Check to see if the provider with `entity_id` is in the ecp IDPList returned by the SP.

#### Parameters

ecp | a LassoEcp |
entity_id | EntityID to check if member of LassoEcp.IDPList |

#### Returns

TRUE if `entity_id` is in LassoEcp.IDPList, FALSE otherwise

### lasso_ecp_is_idp_entry_known_idp_supporting_ecp ()

    gboolean
    lasso_ecp_is_idp_entry_known_idp_supporting_ecp
                                   (LassoEcp *ecp,
                                    const LassoSamlp2IDPEntry *idp_entry);

Check to see if the `idp_entry` is in the `entity_id_list`

#### Parameters

ecp | a LassoEcp |
idp_entry | LassoSamlp2IDPEntry to check if member of `entity_id_list` |

#### Returns

TRUE if `entity_id` is in `idp_list` , FALSE otherwise

### lasso_ecp_set_known_sp_provided_idp_entries_supporting_ecp ()

    void
    lasso_ecp_set_known_sp_provided_idp_entries_supporting_ecp
                                   (LassoEcp *ecp);

The SP may provide a list of LassoSamlp2IDPEntry (LassoEcp.sp_idp_list) which it trusts. The ECP client has a list of IDP EntityID's it knows supports ECP (LassoEcp.known_idp_entity_ids_supporting_ecp). The set of possible IDP's which can service the SP's authn request are the interesection of these two lists (the IDP's the SP approves and IDP's the ECP knows about). This find the common members between the two lists and assign them to LassoEcp.known_sp_provided_idp_entries_supporting_ecp.

#### Parameters

ecp | a LassoEcp |

### lasso_ecp_has_sp_idplist ()

    gboolean
    lasso_ecp_has_sp_idplist (LassoEcp *ecp);

Returns TRUE if the SP provided an IDP List, FALSE otherwise.

#### Parameters

ecp | a LassoEcp |

### lasso_ecp_get_endpoint_url_by_entity_id ()

    gchar *
    lasso_ecp_get_endpoint_url_by_entity_id
                                   (LassoEcp *ecp,
                                    const gchar *entity_id);

Returns the SingleSignOnService SOAP endpoint URL for the specified `entity_id` . If the provider cannot be found or if the provider does not have a matching endpoint NULL will be returned.

#### Parameters

ecp | a LassoEcp |
entity_id | the EntityID of the IdP |

#### Returns

url (must be freed by caller)

### lasso_ecp_process_sp_idp_list ()

    int
    lasso_ecp_process_sp_idp_list (LassoEcp *ecp,
                                   const LassoSamlp2IDPList *sp_idp_list);

The SP may optionally send a list of IdP's it trusts in ecp:IDPList. The ecp:IDPList may not be complete if the IDPList.GetComplete is non-NULL. If so the IDPList.GetComplete is a URL where a complete IDPList may be fetched.

Whenever the IDPList is updated this function needs to be called because it sets the LassoEcp.known_sp_provided_idp_entries_supporting_ecp and the default IdP URL (LassoProfile.msg_url).

The LassoEcp client has a list of IdP's it knows supports ECP (LassoEcp.known_idp_entity_ids_supporting_ecp). The set of IdP's available to select from should be those in common between SP provided IdP list and those known by this ECP client to support ECP.

This routine sets the LassoEcp.known_sp_provided_idp_entries_supporting_ecp list to the common members (e.g. intersection) of the SP provided IdP list and the list of known IdP's supporting ECP.

A default IdP will be selected and it's endpoint URL will be assigned to LassoProfile.msg_url.

If the SP provided an IDP list then the default URL will be taken from first IDPEntry in LassoEcp.known_sp_provided_idp_entries_supporting_ecp otherwise it will be taken from LassoEcp.known_idp_entity_ids_supporting_ecp.

#### Parameters

ecp | a LassoEcp |

### lasso_ecp_new ()

    LassoEcp *
    lasso_ecp_new (LassoServer *server);

Creates a new LassoEcp.

#### Returns

a newly created LassoEcp object; or NULL if an error occured

### lasso_ecp_process_authn_request_msg ()

    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

#### Parameters

ecp | this LassoEcp object |
authn_request_msg | the PAOS authn request received from the SP |

### lasso_ecp_process_response_msg ()

    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

#### Parameters

ecp | this LassoEcp object |
response_msg | the SOAP response from the IdP |

### lasso_ecp_destroy ()

    void
    lasso_ecp_destroy (LassoEcp *ecp);

Destroys a LassoEcp object

#### Parameters

ecp | a LassoEcp |

## Types and Values

### struct LassoEcp

    struct LassoEcp {
    	gchar *assertion_consumer_url;
    	gchar *message_id;
    	gchar *response_consumer_url;
    	gchar *relaystate;
    	LassoSaml2NameID *issuer;
    	gchar *provider_name;
    	gboolean is_passive;
    	LassoSamlp2IDPList *sp_idp_list;
    	GList *known_sp_provided_idp_entries_supporting_ecp; /* of LassoSamlp2IDPEntry */
    	GList *known_idp_entity_ids_supporting_ecp;	         /* of strings */
    };