Skip to content
This repository has been archived by the owner on Nov 29, 2022. It is now read-only.

Authentication statement is too old to be used with value X #207

Open
tomas-forsman opened this issue Aug 25, 2017 · 19 comments
Open

Authentication statement is too old to be used with value X #207

tomas-forsman opened this issue Aug 25, 2017 · 19 comments

Comments

@tomas-forsman
Copy link

The property maxAuthenticationAge make users to be locked out unless set to more than the IDP assertion timeout.

For instance, when logged in to a IDP with assertion timeout of 3 days and if the maxAuthenticationAge is set to a lower value, say 8 hours. The user log in on day one and when trying to reauthenticate on day two the IDP send back the same assertion as the user had on the first day, and has the same authentication time. Spring then validate the assertion against the maxAuthenticationAge which is only 8 hours and throws a CredentialExpiredException. Trying to reauthenticate with the IDP still give the same assertion and is once again validated against the maxAuthenticationAge, so the user can not log in to the SP any more.

Setting the maxAuthenticationAge to more than the IDP assertion time solves the issue, but then what is the use of the property at all?

Also, the IDP assertion already has a NotOnOrAfter which is used to verify that the assertion has expired.

I've not found any reference to maxAuthenticationAge in the SAML specification. I wonder if it would be better to remove this property and let the IDP/SAML protocol handle assertion timeout?

@gstanchev
Copy link

gstanchev commented Aug 25, 2017

We too are running into this issue a lot. The maxAuthenticationAge actually applies lifetime verification saml:AuthnStatement, not on the saml:Assertion itself. The saml:AuthnStatement/AuthnInstance attribute tells the SP when the user was last authenticated at the IdP. I do not like the idea of removing this policy as it might serve a useful purpose but I'd like to see improvement of it's handling. For example, there is the forceAuthN SAML parameter that suggests to the IdP a full reauthentication is desired. So perhaps instead of throwing and dead-ending the users, reattempt the authentication. Of course forceAuthN is dependent on the IdP supporting it and/or honoring it based on it's policy and config. So even that is not a sure bet. Or an option to issue a warning in the logs but letting the authentication succeed. One could argue that the assertion lifetime is the real validity truth. Stricter SPs could still be configured to reject based on maxAuthenticationAge but not by default.

So my proposal would be = add a property
onStaleAuthenticationAgeViolation= { throw | forceAuthN-then-throw | forceAuthN-then-allow-with-warning | allow-with-warning | allow} with default "allow-with-warning"

@antonevane
Copy link

Any updates on that?

@eyaroslavtsev
Copy link

same thing

2 similar comments
@shimpeko
Copy link

same thing

@ricardovdbroek
Copy link

same thing

@suvarnajayanth
Copy link

Hi can we skip this validation maxAuthenticationAge ?

@ottenhoff
Copy link

Hi can we skip this validation maxAuthenticationAge ?

Set a very high value for maxAuthenticationAge, e.g., 86400.

@suvarnajayanth
Copy link

@ottenhoff Yeah i tried this and which will expire 86400 seconds then ,can we remove this validation ?

@suvarnajayanth
Copy link

suvarnajayanth commented Apr 10, 2018

@ottenhoff , I did set maxAuthenticationAge to 365 days , Still for few of users it expired for 21 days , is it only applicable to fresh login after maxAuthenticationAge changes ?

@fhanik fhanik removed status: first-timers-only An issue that can only be worked on by brand new contributors status: waiting-for-triage An issue we've not yet triaged labels Feb 15, 2019
@neergupta
Copy link

Facing same issue. Setting its value to some higher number is equivalent to non-existent of this property. So either the property maxAuthenticationAge should be removed OR the forceAuthN behavior should be delegated in case of old authentication statement.

@wilder
Copy link

wilder commented Sep 19, 2019

Any updates on this?

@skokeh
Copy link

skokeh commented Sep 20, 2019

Hi,
I have same problem, but actually i realized that it's happened only on the same browser.
If i try to login but another browser it's work.

@cellcoresystems
Copy link

cellcoresystems commented Mar 17, 2020

Hi,
I have same problem, but actually i realized that it's happened only on the same browser.
If i try to login but another browser it's work.

That is correct, cause the information is stored in the cookies of browser1.
When you log in with another browser, then you get a new token/cookie in browser2.

As a workaround, you can also delete cookies in browser1 and it should work again after.
But still not a solution ;o)

Best would be to have a forced reauth, rather than a lockout like @gstanchev said .

@SabithaM
Copy link

Hi,
The default values for maxAuthenticationAge and maxAssertionTime are 7200 seconds and 3000 seconds respectively. But is there any max value defined for these properties? I didn't find any information regarding this in the SAML reference document. Can someone help on this?

@jzheaux
Copy link
Contributor

jzheaux commented Jan 19, 2021

@SabithaM, there are no defined maximum values other than the practical limitations of the datatypes used.

@man0s
Copy link

man0s commented May 14, 2021

same thing

@chubbard
Copy link

chubbard commented Sep 21, 2021

So if you want to disable the maxAuthenticationAge check you can set maxAuthenticationAge=-1 and add the following bean:

public class CustomWebSSOProfileConsumer extends WebSSOProfileConsumerImpl {

    @Override
    protected void verifyAuthenticationStatement(AuthnStatement auth, RequestedAuthnContext requestedAuthnContext, SAMLMessageContext context) throws AuthenticationException {
        // Validate that user wasn't authenticated too long time ago
        long maxAuthenticationAge = getMaxAuthenticationAge();
        if (maxAuthenticationAge > 0 && !isDateTimeSkewValid(getResponseSkew(), maxAuthenticationAge, auth.getAuthnInstant())) {
            throw new CredentialsExpiredException("Authentication statement is too old to be used with value " + auth.getAuthnInstant());
        }

        // Validate users session is still valid
        if (auth.getSessionNotOnOrAfter() != null && auth.getSessionNotOnOrAfter().isBeforeNow()) {
            throw new CredentialsExpiredException("Authentication session is not valid on or after " + auth.getSessionNotOnOrAfter());
        }

        // Verify context
        verifyAuthnContext(requestedAuthnContext, auth.getAuthnContext(), context);
    }
}

I think the problem with these checks is that they both throw the CredentialsExpiredException which will result in a dead-end. The next step would be to force re-authentication in the service. To do that you need to set org.springframework.security.saml.websso.WebSSOProfileOptions.forceAuthN to true.

@amit17051980
Copy link

In the organisations where SSO is integrated with the Desktops, users won't be authenticated in interactive mode when launching an app that is configured for SAML SSO. In this scenario, it is worth comparing the SAML Assertion than the AuthNStatement.

@ekisarodney
Copy link

So if you want to disable the maxAuthenticationAge check you can set maxAuthenticationAge=-1 and add the following bean:

public class CustomWebSSOProfileConsumer extends WebSSOProfileConsumerImpl {

    @Override
    protected void verifyAuthenticationStatement(AuthnStatement auth, RequestedAuthnContext requestedAuthnContext, SAMLMessageContext context) throws AuthenticationException {
        // Validate that user wasn't authenticated too long time ago
        long maxAuthenticationAge = getMaxAuthenticationAge();
        if (maxAuthenticationAge > 0 && !isDateTimeSkewValid(getResponseSkew(), maxAuthenticationAge, auth.getAuthnInstant())) {
            throw new CredentialsExpiredException("Authentication statement is too old to be used with value " + auth.getAuthnInstant());
        }

        // Validate users session is still valid
        if (auth.getSessionNotOnOrAfter() != null && auth.getSessionNotOnOrAfter().isBeforeNow()) {
            throw new CredentialsExpiredException("Authentication session is not valid on or after " + auth.getSessionNotOnOrAfter());
        }

        // Verify context
        verifyAuthnContext(requestedAuthnContext, auth.getAuthnContext(), context);
    }
}

I think the problem with these checks is that they both throw the CredentialsExpiredException which will result in a dead-end. The next step would be to force re-authentication in the service. To do that you need to set org.springframework.security.saml.websso.WebSSOProfileOptions.forceAuthN to true.

Cant seem to find org.springframework.security.saml.websso in the spring-security-saml2-core Milestone release. (2.0.0M31)

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Development

No branches or pull requests