Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migrated to Confluence 5.3

I. Introduction

This document is the specification of levels of assurance (LOA) in CAS clients and server.

...

II. Authentication API in CAS server

NOTE by Nathan: I've written a new LOA spec document that is based on the discussion found in this document:  Second Level Of Assurance Specification

A) CAS 3.5.0

In CAS server 3.5.0, an authentication manager is in charge of validating credentials. It takes credentials as input.

...

  • an authentication date
  • attributes
  • a principal with identifier and attributes.

B) CAS 4.0.0

TODO Marvin : describe briefly the new design of the authentication API in CAS server 4.0.0

 

III. New concepts or updated ones for LOA

A) Assurance policy (new)

The CAS server has one and only assurance policy. It consists of many levels of assurance (at least two).

...

The assurance policy is basically a map from a set of authentication attribute constraints, defined in an expression, to descriptive names and numbers.

Example Assurance Policy

Authentication handlers defined for this example:

...

* I just noticed that with this design (and if reusing the "renew" parameter to specify the names of accepted levels), then adding a level named "true" might actually provide backwards compatibility automatically without needing any special code.  Haha!  (wink)  I'm not sure if I'd actually recommend this practice, but it is kind of interesting. -Nathan

Authentication Constraint Expressions

An authentication constraint expression describes a combination of authentication handlers and authentication attributes derived from those handlers that are required to achieve the given level of authentication.  Acceptable authentication handlers can be combined using logical and and or and grouped using parentheses.  Authentication attribute constraints can be defined for each authentication handler. (In this example, they are defined within braces following the authentication handler.)

...

NOTE: As I'm working on my use cases, I'm discovering that the attributes aspect of authentication handlers (other than the pseudo-attributes of "initial" and "timestamp") might be better handled proactively.  In other words, a service that would require a stronger password will probably already be using role-based authorization to allow/deny access.  If there is an interrupt screen in CAS that enforces the stronger password policy based on this role membership (e.g. by looking at Grouper or LDAP group membership), then can be assured that the user has the stronger password if they get past the interrupt screen code.  In that case, we probably don't need to handle attributes at the constraint expression level.  This would reduce the complexity of the assurance evaluator.  On the other hand, it still might be useful to compute a stronger LOA number (or name) based on attributes such as password strength.  Especially when federating with someone who wants NIST-like levels, it might be nice to be able to pass that extra info along.  -Nathan

Authentication Attributes (update)

Authentication attributes come in two flavors: credential attributes and event attributes.  For the most part, these are stored in the Authentication object and placed there by the authentication handler.  However, some of these attributes used in constraint expressions (such as the "initial" attribute in the above examples) will likely be computed on the fly or pulled from other objects.

...

Here's another perspective that can maybe help to get us on the same page:  You can think of my suggestion of "constraint expressions" as a way to dynamically define a new AuthenticationHandler (along with the corresponding Credentials and UserInteraction), composed of other pre-existing handlers, without needing to write code.  Then, each AuthenticationHandler (whether Java-based or expression-based) is given a name and a number.  And, again, I'm not tied to the concept of an expression... I'm more tied to the concept of deployers being able to easily compose existing authentication methods together without writing code (and with automatically also composing all necessary related components like credentials and user interactions).

B) Level of assurance (new)

A level of assurance has :

  • many names (at least one)
  • a level (positive numeric value). 0 means not authenticated. The higher the value is, the more secure the level is.
  • a constraint expression.  see above. -Nathan

By default, the assurance policy is defined with the following levels of assurance :

...

NEW Jérôme :

I'm not tied to my basic solution either. Above all, I want to stick to the most simple solution. I admit that expressions allow composition, which is better than re-coding authentication handlers, credentials...

I have one question though : how do you evaluate the "initial" attribute ? Isn't it an information you only get after authenticating the user in the authentication handler ?

NEW Nathan:

True.  I see three flavors of attributes.  First, you have attributes that would always be true about the user and could be looked up using only partial knowledge of the user (such as by their username).  These include things like password policy enforced and a checklist of procedures followed during signup.  Other attributes are only known once authentication has been complete, such as the timestamp and whether or not SSL was employed.  These attributes would stick around as metadata associated with the "Authentication" object.  (See the AuthenticationMetaDataPopulator interface in the current CAS implementation.)   Finally, some attributes, such as the "initial" attribute, would need to be handled as a special case.  That's because for a given Authentication, this attribute has the value of "true" at first, but then has the value of "false" for every time after that.  Note that I'm not convinced that it would be best to re-implement "renew" as a feature of LOA in this way.  Doing this gives a lot of flexibility, but it might be sufficient to think of it as a separate concern.

NEW 2 Jérôme :

I read carefully your spec. It's an excellent work, I think we're close to a solution we both agree on.

My remarks on you spec and more globally. I agree :

  • on LOA defintion based on authentication handlers ordrerd list
  • with requested "loa" parameter syntax : numeric value means a LOA and superior, name value requests specific LOA
  • that authentication handlers should be linked to user interactions (instead of credentials which are not known from LOA)
  • on using precedence for interactions when having same level of assurance.

But,

  • the user interactions part is not totally clear to me : do you want to have one screen with multiple user interactions or several screens with just one user interaction ? I think also that each interaction should be attached to credentials for further authentication
  • I still belive we can get rid of parameters just by using supports() method on authentication handler : I would say that the supports() method could have more input than just the credentials, but also Authentication, HttpServletRequest... Don't you think ?

NEW 2 Nathan:

 

  • I was imagining that each interaction has a particular "starting screen", which could lead to subsequent screens based on Spring Web Flow and controllers that are triggered from the first screen.
  • If two authentication handlers are required for the requested LOA, then CAS would show the interaction for each handler in sequence.  In this case the user would see two screens, one for the first authentication handler and one for the second.  This allows easy mix-and-match of authentication handlers.
  • The thought is this:
    • Authentication Handler is requested
    • Interaction is selected as defined by the authentication handler
    • First screen of interaction is displayed as defined by the interactionSpring Web Flow and controllers might show additional screens
      • If alternate Interactions (for alternate Authentication Handlers) are available, list links to the alternates on the screen.
    • Spring Web Flow and controllers might show additional screens
    • The interaction results in Credentials
    • The Credentials are handled by the Authentication Handler, producing an Authentication
    • Repeat these steps for any other authentication handlers required for this LOA

 

  • One thing I'm trying to avoid is having to define multiple copies of an authentication handler in order to support things like multiple password policies.  We probably could make that work successfully, but it feels like more work than necessary for deployers.
  • It might be OK to start this way (no parameters but with multiple auth handlers to support multiple password policies) and then sometime in the future re-evaluate options that would make it easier to define LOAs based on password policy strength.  I'll look through our use cases again to determine whether this will work well for us in the short-to-medium time-frame.


B) Level of assurance (new)

A level of assurance has :

  • many names (at least one)
  • a level (positive numeric value). 0 means not authenticated. The higher the value is, the more secure the level is.
  • a constraint expression.  see above. -Nathan

By default, the assurance policy is defined with the following levels of assurance :

LevelNamesExamples
50double_credentialsLogin/password + SMS code
40credentialsLogin/password with local authentication handler
30external_credentialsOAuth (Twitter, Facebook...) authentication
20systemIP based authentication
10cookieRemember-me
0anonymousThe user is not authenticated

C) Authentication handler (update)

So far, an authentication handler authenticates credentials and is defined to support a kind of credentials.

...

I think instead an authentication handler should simply populate its authentication object with appropriate authentication attributes, and the assurance policy should be responsible for mapping authentication handlers (or combinations thereof) to assurance levels. -Nathan

D) Interaction (new)

An interaction is a way to get credentials. Each interaction is defined to support a kind of credentials it will return when called.

...

  • annual acceptable use policy
  • need to increase password strength
  • need to register (or confirm) contact information such as cell #
  • need to select security Q&A
  • need to register device/browser (you've probably seen facebook do this, for example)

I think it would greatly benefit CAS to have a generalized solution for interrupt screens, and I think it could be done without much complexity by simply generalizing the concepts found in LPPE.the concepts found in LPPE.

NEW Jérôme :

I agree. I propose to keep this spec focused on LOA (steps 1, 2 and 3 in roadmap) and start a new spec after for other steps (4 ,5 and 6).

NEW Nathan:

Sounds reasonable.  I wanted to emphasize the ways that interrupt screens will likely play an important role in specific implementations of LOA concepts.  Read these scenarios for more examples: Example LOA Use Cases

E) Interaction manager (new)

An interaction manager is defined with :
  • many interactions (at least one).
An interaction manager is in charge of finding the right interactions to try for a given list of authentication handlers. The interactions are returned as a list to specify in which order interactions are to be tried.

F) Authentication manager (update)

So far, an authentication manager takes credentials as input.
To support LOA, it will now take a numeric level of assurance as input also.
I prefer to think of the "name" of the assurance level as it's primary key, and to think of the numeric value as an attribute.  Therefore, I think the authentication manager should receive the name instead of the number. -Nathan
Jérôme :
I prefer using numeric value because this way, you can have an authentication handler with a LOA value (for example : 49) which is not equals to an already existing LOA.

Nathan:
One issue that we'll need to deal with is authenticator handlers that represent the same numeric "strength" of authentication.  For example, for our second factor we might let users choose either Google Authenticator (if they have a smartphone) or SMS code (if they have an older phone or one that doesn't support the app).  We might want to have the ability to say that these two authentication mechanisms afford the same level of authentication (if that is how we decide to define them), such that the system would allow the user to select the one most appropriate for their circumstance (or ideally we could automatically select the right method if we knew that they were only set up for one of the two).

G) Registered service (update)

So far, a registered service supports attributes : id, name, theme, description, isAnonymous...
To support LOA, it will now define what authentication handlers it supports. None selected means all.
I think it would be better for the registered service to define a list of assurance levels (from the server's policy) that it accepts. -Nathan

H) Assurance evaluator (new)

The assurance evaluator is in charge of evaluating the LOA of the authentication given as input. It returns a numeric value.
Generally, it returns the numeric value of the LOA associated with the authentication handler used to authenticate previously the user and stored in the authentication.
In case of remember-me, the LOA returned is not the one of the authentication handler but is computed.
I would like to redefine the assurance evaluator as the system that evaluates the assurance attribute constraint expressions and determines which level(s) of assurance (single number and possibly multiple names) are fulfilled by the current set of user authentication objects. -Nathan

IV. Extension to CAS protocol

So far, the CAS server supports the renew parameter set to true to force re-authentication whatever the current authentication is.

For backward compatibility, these parameter and value will remain but new values will be possible for the renew parameter to handle LOA :

  • renew=value, the numeric value is strictly positive, it's meant to be a requested numeric LOA
  • renew=name, name is the name of an authentication handler or the name of a level of assurance.  (I recommend allowing the client to specify either a minimum number or a list of names of the level of assurance and not an individual authentication handler.  If that level of flexibility is desired, then the client should be able to specify a complete authentication constraint expression and not just an authentication handler name. Noe that with a list of names, only exact matches count. Even if the user has fulfilled a higher number but not fulfilled the requested type of authentication specified by the named level, then it doesn't count. -Nathan)
Jérôme :
I'm not sure if we should keep the availability to request LOA by authentication handler name of by constraint expression. Does it match real use case ? Does it make sense ? I think we should always request a LOA by name or numeric value, meaning a specific level and ALSO the "superior" levels.
I think I'd prefer if we created a new parameter named "loa" or something like that, instead of reusing "renew".  We would still want to preserve the behavior of "renew=true", but I think that we don't gain much by piggy-backing on the existing parameter.  I don't think it really "costs" us much to add a new "loa" parameter and it makes the protocol more understandable.
Jérôme :
I agree. We can use a parameter named "loa" instead of "renew" to avoid confusion.
Note that behavior is slightly different whether the client requests LOA by name or by number.  Here's an example.  Refer back to the table above under the "Example Assurance Policy" section.   Let's say that a user has satisfied the requirements for level 47 (renewed LDAP authentication with strong password).  In this case, the user's numeric LOA value would be 47, and they would have satisfied the following named levels: strong_ldap_renew, strong_ldap, any_ldap_renew, and any_ldap.  If a service requests "loa=30" (meaning any numeric value >=30), then the user would be allowed to access the service.  But if a service requests "loa=public_idp" (level requested by name), then the user would be prevented from accessing the service, even though their numeric value is higher.
Jérôme :
Using a name or a numeric value of LOA must lead to the same result. The only diffrence between name and numeric value is that a name should match a defined name whereas a numeric value doesn't need to match a numeric LOA because it only relies on numeric comparison (and not on exact matching).
Nathan:
In the use cases that I need to support, our central IT policies and concepts of "better" and "worse" most likely won't be agreed-upon by the entire organization.  This means that in some cases, an app (or a set of apps run by a particular department) might reject an authentication method (considering it weaker) that the rest of the organization has deemed acceptable and considers stronger.  Certainly it would be GREAT if we could just force agreement, but that just isn't the case where I work.  Our central IT department doesn't have that authority.  It would be very helpful to be able to support exceptions to the rule.
Another way to think of it is this:  This concept extends beyond pure "levels" of authentication (where one is always better than another) to "types" of authentication (where each type has pros and cons that make it better or worse under varying circumstances).  One example would be related to PCI compliance.  As an organization, we might say that the two-factor combination of a simple password plus Google Authenticator is stronger than a complex password.  But PCI rules might say that all users need a strong password regardless of whether or not they have Google authenticator.  Thus, the systems that need to be PCI compliant would need to be configured to handle an exception to the rule and reject something that the rest of the organization thinks is strong
one of the two).

G) Registered service (update)

So far, a registered service supports attributes : id, name, theme, description, isAnonymous...
To support LOA, it will now define what authentication handlers it supports. None selected means all.
I think it would be better for the registered service to define a list of assurance levels (from the server's policy) that it accepts. -Nathan

H) Assurance evaluator (new)

The assurance evaluator is in charge of evaluating the LOA of the authentication given as input. It returns a numeric value.
Generally, it returns the numeric value of the LOA associated with the authentication handler used to authenticate previously the user and stored in the authentication.
In case of remember-me, the LOA returned is not the one of the authentication handler but is computed.

I would like to redefine the assurance evaluator as the system that evaluates the assurance attribute constraint expressions and determines which level(s) of assurance (single number and possibly multiple names) are fulfilled by the current set of user authentication objects. -Nathan

IV. Extension to CAS protocol

So far, the CAS server supports the renew parameter set to true to force re-authentication whatever the current authentication is.

For backward compatibility, these parameter and value will remain but new values will be possible for the renew parameter to handle LOA :

  • renew=value, the numeric value is strictly positive, it's meant to be a requested numeric LOA
  • renew=name, name is the name of an authentication handler or the name of a level of assurance.  (I recommend allowing the client to specify either a minimum number or a list of names of the level of assurance and not an individual authentication handler.  If that level of flexibility is desired, then the client should be able to specify a complete authentication constraint expression and not just an authentication handler name. Noe that with a list of names, only exact matches count. Even if the user has fulfilled a higher number but not fulfilled the requested type of authentication specified by the named level, then it doesn't count. -Nathan)
Jérôme :
I'm not sure if we should keep the availability to request LOA by authentication handler name of by constraint expression. Does it match real use case ? Does it make sense ? I think we should always request a LOA by name or numeric value, meaning a specific level and ALSO the "superior" levels.
I think I'd prefer if we created a new parameter named "loa" or something like that, instead of reusing "renew".  We would still want to preserve the behavior of "renew=true", but I think that we don't gain much by piggy-backing on the existing parameter.  I don't think it really "costs" us much to add a new "loa" parameter and it makes the protocol more understandable.
Jérôme :
I agree. We can use a parameter named "loa" instead of "renew" to avoid confusion.

Note that behavior is slightly different whether the client requests LOA by name or by number.  Here's an example.  Refer back to the table above under the "Example Assurance Policy" section.   Let's say that a user has satisfied the requirements for level 47 (renewed LDAP authentication with strong password).  In this case, the user's numeric LOA value would be 47, and they would have satisfied the following named levels: strong_ldap_renew, strong_ldap, any_ldap_renew, and any_ldap.  If a service requests "loa=30" (meaning any numeric value >=30), then the user would be allowed to access the service.  But if a service requests "loa=public_idp" (level requested by name), then the user would be prevented from accessing the service, even though their numeric value is higher.
Jérôme :
Using a name or a numeric value of LOA must lead to the same result. The only diffrence between name and numeric value is that a name should match a defined name whereas a numeric value doesn't need to match a numeric LOA because it only relies on numeric comparison (and not on exact matching).

Nathan:
In the use cases that I need to support, our central IT policies and concepts of "better" and "worse" most likely won't be agreed-upon by the entire organization.  This means that in some cases, an app (or a set of apps run by a particular department) might reject an authentication method (considering it weaker) that the rest of the organization has deemed acceptable and considers stronger.  Certainly it would be GREAT if we could just force agreement, but that just isn't the case where I work.  Our central IT department doesn't have that authority.  It would be very helpful to be able to support exceptions to the rule.
Another way to think of it is this:  This concept extends beyond pure "levels" of authentication (where one is always better than another) to "types" of authentication (where each type has pros and cons that make it better or worse under varying circumstances).  One example would be related to PCI compliance.  As an organization, we might say that the two-factor combination of a simple password plus Google Authenticator is stronger than a complex password.  But PCI rules might say that all users need a strong password regardless of whether or not they have Google authenticator.  Thus, the systems that need to be PCI compliant would need to be configured to handle an exception to the rule and reject something that the rest of the organization thinks is strong.

NEW Jérôme :
Just to be sure : you want to keep the ability to request a specific authentication method (and not a level of authentication), correct ?
But, how do you do that with authentication constraint ? What do you imagine as a syntax ?

NEW Nathan:
Take a look at bottom this document for a description: Example LOA Use Cases
Note that I've simplified the concept of the "constraint expression" so that it basically is simply an ordered list of authentication handlers (with attributes) that all need to be fulfilled.  I've eliminated "OR" and grouping, since these can be handled in other ways.

V. Main algorithm

A) Diagram

B) Requested LOA

1) Client requested LOA

A client requested LOA is computed from the renew parameter if this one is defined :

  • If renew is a numeric value, all authentication handlers whose LOA is superior or equals are selected
  • If renew is a LOA name, the associated numeric value is used to find the authentication handlers as previously
  • If renew is an authentication handler name, the authentication handler is selected.

2) Server requested LOA

A server requested LOA is computed from the requested registered service (service parameter).

...

If no service is defined, all authentication handlers are requested.

3) Computed requested LOA

The requested authentication handlers are the intersection between the ones computed for client and the ones computed for server.

...

The requested LOA is the lowest numeric value of all selected authentication handlers.

C) Current LOA

The current LOA is retrieved from the authentication using the assurance evaluator.

D) Compare requested LOA and current LOA

If the current LOA is equals or superior to requested LOA, a service ticket is generated and the user is redirected to the service with this service ticket or to the generic login successfull view is displayed (if no service is requested).

If the current LOA is strictly inferior to the requested LOA, an authentication process should be started.

E) Define the needed interactions

At this step, we have the requested authentication handlers and LOA.

...

If no interaction is returned, a CAS error page is displayed : "The CAS server cannot grant the level of assurance requested by service and/or by renew parameter".

F) Process interactions

At this step, we have a list of ordered interactions to use for authentication process.

...

  • If the principal is null, the user is redirected back to the view with an error message. If the principal is not null, the user is authenticated and we can generate a service ticket and redirect him to the service or display the generic login successfull view (if no requested service).
If no more interaction is available (no interaction was able to authenticate successfully a user), a CAS error page is displayed : "The CAS server cannot grant the level of assurance requested by service and/or by renew parameter".

G) Communication with Client

Ideas for a new CAS Protocol for Ticket Validation Response   -Nathan

...

  • NOT NECESSARILY RELATED TO LOA: user-attributes - contains attributes of the user (principal)
    • attrib - subject to the attribute release policy associated with this service - basically the same as the attributes in the SAML validation response
  • loa-number - the maximum number associated with any of the satisfied levels of assurance
  • levels-satisfied - list of the names of all assurance levels that were satisfied by the users's current session
    • level - the name of the level of assurance
  • MAYBE: auth-handlers - list of all auth handlers that have successfully authenticated for the user's current session (i.e. authentication objects) - note: this might not be needed or desired
    • auth-handler - an individual auth handler; the "name" XML attribute contains the name
      • attrib - each attribute in the authentication object can be listed here.  probably require deployer to specify which attributes should be released, or maybe include a release policy for registered services similar to that for user attributes
Jérôme :
Yes, it would be great to return user attributes.
Regarding LOA, I would return the current LOA of the user with numeric value and names, and I would add the authentication handler name used to authenticate the user.
But I thought we wanted to add these information to the SAML validation, not to the CAS one, to keep backward compatibility...

Nathan:
It would probably be fine to go that route (i.e. support the new LOA stuff only within SAML), but there was talk on the cas-dev mailing list about possibly coming out with a new revision of the CAS protocol (probably listening at a different URL), to add these types of things.

NEW Jérôme :
I agree, it would be great to improve CAS validation response, we have to try to get an agreement on that....

VI.

...

Use cases

A) 2 webapps supporting remember-me and authentication by credentials / client requested LOA

- I access app1 and app2 as remember-me (round-trips on /login)
- I access a more secured area (requiring login/password authentication) in app2 -> I'm redirected to CAS server with renew=credentials, I need to re-authenticate, I fill my password and I'm redirected to app2 -> I get access as I'm now authenticated (not remembered)
- I access a more secured area (requiring login/password authentication) in app1 : what happens ? I'm still remembered in this one, so I'm redirected back to CAS server with renew=credentials and as I'm now authenticated in SSO session with the right LOA, I'm redirected back to application with a valid service ticket.

B) Other use cases

Note that some of these are various versions of the same story but using different scenarios.

...

Nathan:  I think this scenario is actually much easier if we allow composition of handlers instead of using a custom combined handler.  The service requests the "LDAP + SMS" multifactor-LOA.  The server realizes that "LDAP" authentication is already fulfilled, so it simply sends the user through the "SMS" interaction and authentication handler.  If the handlers were hard-coded together into a single handler and a single interaction, there would be no easy way for the server to send the user through only the second half of the interaction and run only the second half of the authentication handler with the second-half of the credentials.  However, if the two authentication handlers are kept separate but simply composed together in the configuration, it would be easy for the server to trigger only the SMS parts of the flow.

VII. Roadmap

A)

...

Step 1

...

: only client requested LOA

For a first versionstep, the idea is to target only the LOA requested by the client (renew parameter).

It means creating the assurance policy, level of assurance and assurance evaluator, updating the authentication handler and the authentication manager and implementing the main algorithm (impacts on webflow).

B)

...

Step 2

...

: add server requested LOA

For a second versionstep, we can add the requested LOA defined in CAS server.

It means updating the registered service, the services management webapp and the main algorithm.

C)

...

Step 3

...

: add interactions

For a third versionstep, we can finally add the interactions and interactions manager and update the main algorithm (impacts on webflow).

NEW Jérôme :

D)

...

Step 4 : add interrupt screens

By extending the current LPPE feature, a mechanism of interrupt screens could be created.

E) Step 5 : return "real" SAML information to clients

It would be usefull to return "real" SAML information, i.e. authentication contexts to the client through SAML validation.

...

F) Step 6 : support SAML authentication requests

To be able to handle very complex client requests on LOA with many parameters (and without previous definition on CAS server), the CAS server should be able to handle SAML authentication requests on /login url.

...