In the SAML2 specification there are several places in an assertion where it is possible to specify a lifetime.
The <SubjectConfirmationData> element contains a NotOnOrAfter attribute.
The <Conditions> element contains a NotOnOrAfter attribute.
The <AuthnStatement> element contains a SessionNotOnOrAfter attribute.
What is the meaning of each of them? How do they relate to each other?
Specifically, which of them must be checked when...
... consuming an incoming Saml2Response using Web SSO
... establishing an application session in the SP
... refreshing (extending) an application session in the SP
... forwarding an assertion to a web service, to act on behalf of the subject (as described by #Thuan)
... issuing a single logout request to the idp, to ensure that the idp still knows of the session?
Each of the NotOnOrAfters are described in the SAML2 core specification. I've included the parts that I can find that describes these attributes here.
SubjectConfirmationData/#NotOnOrAfter
A time instant at which the subject can no longer be confirmed. The time value is encoded in UTC, as described in Section 1.3.3.
Note that the time period specified by the optional NotBefore and NotOnOrAfter attributes, if present, SHOULD fall within the overall assertion validity period as specified by the element's NotBefore and NotOnOrAfter attributes. If both attributes are present, the value for NotBefore MUST be less than (earlier than) the value for NotOnOrAfter.
Conditions/#NotOnOrAfter
Specifies the time instant at which the assertion has expired. The time value is encoded in UTC, as described in Section 1.3.3.
The NotBefore and NotOnOrAfter attributes specify time limits on the validity of the assertion within the context of its profile(s) of use. They do not guarantee that the statements in the assertion will be correct or accurate throughout the validity period. The NotBefore attribute specifies the time instant at which the validity interval begins. The NotOnOrAfter attribute specifies the time instant at which the validity interval has ended. If the value for either NotBefore or NotOnOrAfter is omitted, then it is considered unspecified. If the NotBefore attribute is unspecified (and if all other conditions that are supplied evaluate to Valid), then the assertion is Valid with respect to conditions at any time before the time instant specified by the
NotOnOrAfter attribute. If the NotOnOrAfter attribute is unspecified (and if all other conditions that are supplied evaluate to Valid), the assertion is Valid with respect to conditions from the time instant specified by the NotBefore attribute with no expiry. If neither attribute is specified (and if any other conditions that are supplied evaluate to Valid), the assertion is Valid with respect to conditions at any time.
If both attributes are present, the value for NotBefore MUST be less than (earlier than) the value for NotOnOrAfter.
AuthnStatement/#SessionNotOnOrAfter
Indicates an upper bound on sessions with the subject derived from the enclosing assertion. The time value is encoded in UTC, as described in Section 1.3.3. There is no required relationship between this attribute and a NotOnOrAfter condition attribute that may be present in the assertion. It's left to profiles to provide specific processing rules for relying parties based on this attribute.
I cross-posted this question to the SAML-dev mailing list and got an answer from Scott Cantor, who has been an editor on the specifications.
The times in the <SubjectConfirmationData> signals for how long time assertion can be tied to the subject. In Web SSO where the subject confirmation method "bearer" is usually used, it means that within this time we can trust that the assertion applies to the one providing the assertion. The assertion might be valid for a longer time, but we must create a session within this time frame. This is described in the Web SSO Profile section 4.1.4.3. The times in <SubjectConfirmationData> must fall within the interval of those in <Conditions>.
The times in <Conditions> is the validity of the entire assertion. It should not be consumed after this time. There is nothing preventing a user session on an SP to extend beyond this point in time though.
SessionNotOnOrAfter is something completely different that is not directly related to the lifetime of the assertion or the subject. It is a parameter the idp can use to control how long an SP session may be. Please note that this parameter is defined that it SHOULD be handled by an SP according to the SAML2Core spec, but far from all SP implementations do. An example of an implementation that does is as usual Shibboleth, that always will respect the occurence of this parameter. When using Single Logout, this parameter is more critical, as it synchronizes the timeout of the session on both the SP and the Idp, to ensure that an SP does not issue a logout request for a session no longer known to the Idp.
In my opinion, only the authors of Saml2 specification can clearly answer this question. I also guess they can write a 10000-page book to explain about many "why" questions about the spec that people have asked for years. Anyway, based on my limited knowledge and on the use cases I have experienced with, my interpretation of those properties is:
Let's look at an example:
SSO: An SP receives an assertion from an IdP and log the user on.
Bootstrap token: The SP saves the assertion as a bootstrap token for later use.
The SP uses the bootstrap token to exchange for an ActAs token so that it can be used to access another web service. It will also cache the token for further uses to avoid having to exchange a new token often, as long as that token is still valid.
For (1), an assertion is valid when and only when both SubjectConfirmationData.NotOnOrAfter and Conditions.NotOnOrAfter are valid. Since the assertion is valid, the SP will create a login session for the user. How long the session should be is specified by the SessionNotOnOrAfter value.
How about 3? I would say the token is considered valid when Conditions.NotOnOrAfter is still valid. According to Scott Cantor: "Processing rules are specific to profiles and the context of use." Source: https://lists.internet2.edu/sympa/arc/mace-opensaml-users/2011-05/msg00007.html In that link they also discussed about the lifetimes of Subject and Conditions in which Conditions usually has longer lifetime than that of the Subject.
Related
According to the SAML 2.0 specification, the NameQualifier attribute in the NameID element is "the security or administrative domain that qualifies the name. This attribute provides a means to federate names from disparate user stores without collision."
My question is: can the "disparate user stores" be within the same IDP? If so, given that the Format of the NameID will be urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified, does the IDP have the right to send anything in the name qualifier as long as it is unique to each of its datastore?
Does this mean that in order for the SP (provided it receives requests from different IDPs) to achieve uniqueness, it has to consider the remote entity ID, NameQualifier and NameID value?
Let's imagine you have a REST resource Restriction (think of a roadblock) that has some filters (e.g. street, direction etc.). The restriction has an expiry which is a datetime. It is only considered in the application logic, when the expiry is in the future or unset/null (no expiry).
Now with procedural style, I could just have a method on the restriction saying expire() which would set the expiry to the current time.
With REST we modify the state of resources instead. I am torn between these more or less functionally equivalent API definitions:
PATCH /restrictions/{id}
data = {
"expiry": 1558654742
}
Client explicitly sets the expiry. This bears the risk of user error with time zones, wrong host clocks etc. Also the client is not supposed to have any choice other than current time.
PATCH /restrictions/{id}
data = {
"expired": true
}
The expired field is a transient virtual property that is translated on the backend to expiry = now. This might be confusing for clients. Also the value for expired can be only true, so there's some redundancy here.
DELETE /restrictions/{id}
Resource stays persisted (soft delete), but is not returned by GET on the collection, which only returns non-expired restrictions. There is no GET on individual restrictions.
PUT /restrictions/{id}/expiry
data = {}
Creates a new virtual resource (no other methods on this path) which represents the expiry. Not sure whether PUTs without any data are idiomatic though.
Right now I do not plan on returning individual restrictions, and the list of all restrictions will return only the non-expired ones by default.
Which one of those methods would you consider the most idiomatic and obvious for a RESTful web service?
If the resource will return a 404 after expiring, DELETE is a great method for this.
Which one of those methods would you consider the most idiomatic and obvious for a RESTful web service?
If you want idiomatic REST, think about how you would do it with a web site.
You'd probably start with GET /restrictions/{id}, and in addition to data about the restriction there would be a form -- maybe embedded in the representation, maybe in the representation of another resource but available via link. You would then submit that form, which would bundle up the fields into an application/x-www-form-urlencoded docement included in a POST request. You could use any URI as the action of the form (and therefore the target-uri of the POST request), but the most useful would probably be POST /restrictions/{id}, because HTTP compliant clients will know to invalidate any previously cached representations of /restrictions/{id}.
Right now I do not plan on returning individual restrictions, and the list of all restrictions will return only the non-expired ones by default.
Same game, but instead of using an identifier for the individual restriction, you would use the uri for the-list-of-non-expired-restrictions. Your resource model doesn't have to match your data model.
There's no rule that says the content-type of a POST must be application/x-www-form-urlencoded. You could post other representations, including your own custom types if that makes things easlier (of course, you have to document the type, and the only clients that are going to send the type are those that have implemented it; the big advantage to the standard media types is that you get lots of clients "for free".)
PUT and PATCH are acceptable alternatives if modifying representations directly seems reasonable. PUT (and probably PATCH, by inference) doesn't actually require that the server accepts the requests as is:
A successful PUT of a given representation would suggest that a subsequent GET on that same target resource will result in an equivalent representation being sent in a 200 (OK) response.
However, there is no guarantee that such a state change will be observable, since the target resource might be acted upon by other user agents in parallel, or might be subject to dynamic processing by the origin server, before any subsequent GET is received. A successful response only implies that the user agent's intent was achieved at the time of its processing by the origin server.
There are conventions to be followed in the response that distinguish "I accepted your representation as is" from other responses.
One of the few constraints REST has is the one of cacheability. The constraints, as the name implies, are, according to Fielding, not an option, even though he talked about hypermedia in this context. Though the general rule applies here as well.
Caching allows local or intermediary applications, so called caches, to store the response of a certain URI for a certain amount of time and if a further safe request for that same URI hits the cache, the cache will serve the client with its stored response rather then routing the request to the server.
In case of your expiration you need to include thoughts about the expiration of such cached values as well, otherwise caches might still serve clients with data that shouldn't exist further.
HTTP talks about caching in RFC 7234 in detail and responses may tell a cache for how long a resource should be considered fresh via either the Cache-Control header or the Expires header. If both are present the former one wins. In example a response header such as Cache-Control: max-age=3600 defines that a response should be considered fresh for up to 3600 seconds while Expires should use a date-time format specified in RFC 7231 such as Expires: Fri, 24 May 2019 05:20:00 CET.
Unfortunately though, RFC 7234 does not talk about how a client can set such a directive actively, as this is considered a server task. Cache-Control does provide some request headers, though these are more of indications that a client either will or wont accept stale data, but not directives to the server to set a respective expiration date. Usually, if a client does not want a certain resource to be further available it should DELETE the resource. If you read up on DELETE though, you might be astonished that it actually does not guarantee that the resource will ever be removed at all. All it states is, that after successfully processing such a request the mapping of the URI to the resource is removed. Whether the same resource is accessible through a different URI or not is not is a different story. "Customizing" DELETE with some kind of parameter to remove the resource after a certain amount of time might work for your API, though might not be understandable for different kind of APIs, therefore this is not recommendable in general.
By using PATCH the information on the expiration timestamp needs to be part of the resource itself. Usually such an information is considered a meta data of a resource and not the or part of the actual data. Therefore I'm not in favor for PATCH either, though this is clearly an opinionated take.
If all of the other HTTP methods do not fit the bill, POST should be taken, as here the server will process the request according to its own semantic. It may apply different heuristics upon receiving different payloads on the same endpoint as well. If you'd have to design such a feature on the Web you may have an edit page of an entry where you have the option to set an expiration date. Upon clicking the submit button of the form your browser is performing a POST request, including the expiration date, and the server will know what to do based on certain heuristics available on the server. I.e. the availability of the expiration date field in the request may instruct the server to actually queue a removal of the entry, update the expiration date meta data of the target resource and return an updated Cache-Control: max-age=... or Expires: ... header on incoming requests to also inform caches about not shipping cached responses of that resource past that time point.
Usually, unsafe operations, like POST, PUT or DELETE invalidate cached responses of a target resource by default, in a case where two users perform cacheable GET requests against a server, both having an intermediary cache in between that differs from the intermediary cache of the other user, and user 1 now expires the origin resource, there might be a case where user 2 will still get served by "his" intermediary cache for the target resource, even though the resource was already deleted on the origin server as his intermediary cache still sees the response as fresh enough and therefore serves use 2 with that stored response. The cached response of the target URI in user 1's cache should already have been removed by the initial POST request but also any eventually cacheable response might have returned an updated cache header and thus led to an expiration at the specified time point. It is therefore important to set the time values for the cache not to high into the future, but also not to short so that caching gets useless.
For resources that may be critical to get removed and not served by caches, in order to prevent the above mentioned case it is probably best to specify Cache-Control: no-cache in general so that such entries are not stored by caches further and requests are directly processed by the API/server itself.
To sum up this post, something like an expiration time point should be considered meta-data of a resource and not main-data. While DELETE may sound great at first, it does not support a removal after some time and an other API might perform such a request immediately, besides not guaranteeing to really remove that resource at all. POST, as the all-purpose toolset of HTTP, or other HTTP operations such as PUT or PATCH may be used here as well, even though the latter "work" under the premise that the body of a request belongs to the actual data of the resource. You should also consider caching into your design and use either Cache-Control: max-age=... or Expires: ... if your resource is non-critical or Cache-Control: no-cache in case of resources that must not ever (for whatever reason) return outdated information to clients. Regardless of the HTTP method you use, you should also think about how the server is allowing the client to set this option in general. Similar to the Web, a form-based solution avoids out-of-band information and thus simplifies the interaction with the API in general, as all of the information are already provided or are obtainable via further links.
According to the docs of Identity Server, there's always the following four claims provided in each token:
Issuer name - iss
Client ID - client_id
Lifetime - exp
Scope - nbf
Given the lifetime is computed as expiration occasion, I understand all of the codes except for the last one. What does the code "NBF" stand for?
I even checked the disambiguation on Wikipedia but there's nothing relating tokens at all.
Bonus question. What's the reason behind the codes being of different format? I can't help wondering why client_id isn't following the same pattern and set to cid. I sense some historical context...
Not before
That's what nbf means.
The usage of this claim is optional and it identifies the time before which the token must not be accepted.
See the definition from the RFC 7519:
4.1.5. "nbf" (Not Before) Claim
The nbf (not before) claim identifies the time before which the
JWT MUST NOT be accepted for processing. The processing of the
nbf claim requires that the current date/time MUST be after or
equal to the not-before date/time listed in the nbf claim.
Implementers MAY provide for some small leeway, usually no more
than a few minutes, to account for clock skew. Its value MUST be a
number containing a NumericDate value. Use of this claim is
OPTIONAL.
The lifespan of the token starts after the time stated in the nbf claim and ends at the time stated in the exp claim.
Addressing your bonus question:
It's important to highlight that nbf is a standard claim registered in IANA while client_id is not. But it doesn't prevent client_id to be used.
Claim names can be defined at will by those using JWTs. The claims defined in the RFC 7519, however, are intentionally short:
All the names are short because a core goal of JWTs is for the representation to be compact.
This document also states the following:
Because a core goal of this specification is for the resulting representations to be compact, it is RECOMMENDED that the name be short -- that is, not to exceed 8 characters without a compelling reason to do so.
From http://saml.xml.org/assertions,
" Note that a SAML response could contain multiple assertions, although its more typical to have a single assertion within a response."
But I want to know some practical scenarios where multiple assertions are needed.
Assertions are claims made by the Identity Provider (IdP). An Attribute is contained in an AttributeStatement, so email address, first name, surname etc would be Attribute instances in an AttributeStatement contained in a single Assertion. Each Assertion needs a Subject and can be used for different things. Normally there is only one Assertion containing an AuthenticationStatement and an AttributeStatement containing Attribute instances.
One use case for multiple Assertion could be a claim about the Subject that is time limited differently from the Attribute list. e.g. perhaps some fact about the user that should only be relied on for a short period of time, defined by Conditions->NotBefore->NotOnOrAfter. Perhaps some authentication mechanism that only allows users to be authenticated at the IdP for a short period of time, compared to the longer period of time their Attribute list can be used for.
You can see a use case for multiple Assertion in a SAMLResponse here.
In SAML metadata file there are several NameID format defined, for example:
<NameIDFormat>urn:mace:shibboleth:1.0:nameIdentifier</NameIDFormat>
<NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified</NameIDFormat>
<NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</NameIDFormat>
Can anybody explain what are these used for? What are the differences?
Refer to Section 8.3 of this SAML core pdf of oasis SAML specification.
SP and IdP usually communicate each other about a subject.
That subject should be identified through a NAME-IDentifier , which should be in some format so that It is easy for the other party to identify it based on the Format.
All these
1.urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified [default]
2.urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress
3.urn:oasis:names:tc:SAML:2.0:nameid-format:persistent
4.urn:oasis:names:tc:SAML:2.0:nameid-format:transient
are format for the Name Identifiers.
The name format for a transient ID in SAML 1 is urn:mace:shibboleth:1.0:nameIdentifier and in SAML 2 is urn:oasis:names:tc:SAML:2.0:nameid-format:transient
Transient is for [section 8.3.8 of SAML Core]
Indicates that the content of the element is an identifier with
transient semantics and SHOULD be treated as an opaque and temporary
value by the relying party.
Unspecified can be used and it purely depends on the entities implementation on their own wish.
About this I think you can reference to http://docs.oasis-open.org/security/saml/Post2.0/sstc-saml-tech-overview-2.0.html.
Here're my understandings about this,
with the Identity Federation Use Case to give a details for those concepts:
Persistent identifiers-
IdP provides the Persistent identifiers, they are used for linking to the local accounts in SPs, but they identify as the user profile for the specific service each alone. For example, the persistent identifiers are kind of like : johnForAir, jonhForCar, johnForHotel, they all just for one specified service, since it need to link to its local identity in the service.
Transient identifiers-
Transient identifiers are what IdP tell the SP that the users in the session have been granted to access the resource on SP, but the identities of users do not offer to SP actually. For example, The assertion just like “Anonymity(Idp doesn’t tell SP who he is) has the permission to access /resource on SP”. SP got it and let browser to access it, but still don’t know Anonymity' real name.
unspecified identifiers-
The explanation for it in the spec is "The interpretation of the content of the element is left to individual implementations". Which means IdP defines the real format for it, and it assumes that SP knows how to parse the format data respond from IdP. For example, IdP gives a format data "UserName=XXXXX Country=US", SP get the assertion, and can parse it and extract the UserName is "XXXXX".
It is just a hint for the Service Provider on what to expect from the NameID returned by the Identity Provider. It can be:
unspecified
emailAddress – e.g. john#company.com
X509SubjectName – e.g. CN=john,O=Company Ltd.,C=US
WindowsDomainQualifiedName – e.g. CompanyDomain\John
kerberos– e.g. john#realm
entity – this one in used to identify entities that provide SAML-based services and looks like a URI
persistent – this is an opaque service-specific identifier which must include a pseudo-random value and must not be traceable to the actual user, so this is a privacy feature.
transient – opaque identifier which should be treated as temporary.
1 and 2 are SAML 1.1 because those URIs were part of the OASIS SAML 1.1 standard. Section 8.3 of the linked PDF for the OASIS SAML 2.0 standard explains this:
Where possible an existing URN is used to specify a protocol. In the case of IETF protocols, the URN of the most current RFC that specifies the protocol is used. URI references created specifically for SAML have one of the following stems, according to the specification set version in which they were first introduced:
urn:oasis:names:tc:SAML:1.0:
urn:oasis:names:tc:SAML:1.1:
urn:oasis:names:tc:SAML:2.0: