Risk-based authN
Philip Brusten
philip.brusten at kuleuven.be
Thu Jun 1 04:32:45 EDT 2017
Hi,
This is a high-level-summary of what we achieved till now. We had to add
certain things to the system configs to hook in to the authentication
flow, so that is not ideal, but it is a proof-of-concept.
- REST-service:
- responsible for collecting audit logs from trusted sources. We
also have a registry of people who go abroad (e.g. congress) which we
included as a source information. The service will calculate the GeoInfo
based on the IP (for now country, longitude, latitude, accuracyradius &
lookuptime)
- endpoint to calculate the risk of a idp login event. The service
responds with a score between 0-100. The higher, the better and thus
more trusted.
- IdP modifications:
- Read browser fingerprint (using
https://github.com/Valve/fingerprintjs2).
- Added fingerprint flow & view which is called everytime just
before "PopulateClientStorageLoadContext" in the sso-abstract-flow. The
view creates the fingerprint in the browser and it will be added to a
FingerprintContext. I added the flow at that location because we needed
Javascript interation with the browser everytime the user communicates
with the IdP (e.g. new login, but also SSO).
- Added the fingerprint to the audit log
- Added a Java-REST-client to communicate with the above REST-service
- Calculated the risk at:
- MFA-authentication flow after we know who the user is
(authn/Password of authn/SPNEGO) we check if the user did an opt-in for
our strong authentication solution, if so it will always be triggered.
If not, we check if there is any risk envolved, if so, we trigger strong
authentication. I added our TransitionMap an nextFlowStrategy below.
- We disabled to consistentAddress-check
(idp.session.consistentAddress = false), so sessions could roam accross
different IPs. As a countermeasure, we analyze the risk in the
authn-flow.xml (right after "PopulateSessionContext"). I the risk is to
high (or trust is to low), we remove the IdP session, so the user must
authenticate, otherwise the user could just use its existing session.
JSON-payload we send from the IdP to our risk calculator:
{
"uid":"user1",
"app":"entityID_of_SP",
"fingerprint":"d8290e99db4af4632fba4b3ed09872",
"auth":"urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport",
"ip":"8.8.8.8"
}
We calculate risk (or trust, depends on how you look at it) based on:
- known fingerprint?
- known IP?
- realistic traveltime (from location A to B in X time)?
- normal time?
- normal location?
- more trusted IP-ranges (e.g. from managed devices)
- user resides in country which we knew already (congress)
- blacklisting
- etc
It would be nice to get some comments on this design. Did we hook in at
the right places or not?
If we have this solution in place, I think we could better sell our
strong authentication solution (https://www.n-auth.com) to our users, as
we can offer them session roaming and perhaps even longer session duration.
Regards,
Philip
MFA-authentication flow:
<util:map id="shibboleth.authn.MFA.TransitionMap">
<entry key="">
<bean parent="shibboleth.authn.MFA.Transition"
p:nextFlowStrategy-ref="selectFirstFactor" />
</entry>
<entry key="authn/SPNEGO">
<bean parent="shibboleth.authn.MFA.Transition">
<property name="nextFlowStrategyMap">
<map>
<entry key="ReselectFlow" value="authn/Password" />
<entry key="proceed" value-ref="checkSecondFactor" />
</map>
</property>
</bean>
</entry>
<entry key="authn/Password">
<bean parent="shibboleth.authn.MFA.Transition"
p:nextFlowStrategy-ref="checkSecondFactor" />
</entry>
<!-- An implicit final rule will return whatever the final flow
returns. -->
</util:map>
<bean id="checkSecondFactor"
parent="shibboleth.ContextFunctions.Scripted" factory-method="inlineScript"
p:customObject-ref="customObjectsToSelectSecondFactor">
<constructor-arg>
<value>
<![CDATA[
nextFlow = 'authn/multifactor';
// Go straight to second factor if we have to, or set up
for an attribute lookup first.
authCtx =
input.getSubcontext("net.shibboleth.idp.authn.context.AuthenticationContext");
mfaCtx =
authCtx.getSubcontext("net.shibboleth.idp.authn.context.MultiFactorAuthenticationContext");
//check is the current MFA-conftext is already acceptable,
if so check if the user did an opt-in, otherwise finish (with value 'null')
if (mfaCtx.isAcceptable()) {
logger.debug('MFA context is already acceptable but
now we will check if there is an opt-in set for multifactor');
// Attribute check is required to decide if first
factor alone is enough.
resCtx =
input.getSubcontext("net.shibboleth.idp.attribute.resolver.context.AttributeResolutionContext",
true);
resCtx.setPrincipal(input.getSubcontext("net.shibboleth.idp.authn.context.SubjectCanonicalizationContext").getPrincipalName());
logger.debug('resolving attrs for ' +
input.getSubcontext("net.shibboleth.idp.authn.context.SubjectCanonicalizationContext").getPrincipalName());
resCtx.getRequestedIdPAttributeNames().add("MFAPreferredMethod");
resCtx.resolveAttributes(custom.get("resolverservice"));
// Check for an attribute that authorizes use of
first factor.
attribute =
resCtx.getResolvedIdPAttributes().get("MFAPreferredMethod");
// set the nextFlow to null and exit MFA-flow when:
// a: There are no values for MFAPreferredMethod
(attribute==null) -> not true in case of opt-in
// b: MFAPreferredMethod is set, but does not
contain 'MobileTwoFactorContract' -> not true in case of opt-in
if (attribute == null || (attribute != null && !
attribute.getValues().contains(new
valueType("urn:oasis:names:tc:SAML:2.0:ac:classes:MobileTwoFactorContract"))))
{
//calculate risk
risk = custom.get("riskPredicate").apply(input);
logger.debug('Risk check result: ' + risk);
if ( risk == false ) {
nextFlow = null;
}
}
input.removeSubcontext(resCtx); // cleanup
}
nextFlow; // pass control to second factor or end
with the first
]]>
</value>
</constructor-arg>
</bean>
On 9/05/2017 16:39, Philip Brusten wrote:
> Hi,
>
> we are thinking about making a service which collects information from
> trusted sources with information like: timestamp, application, userid,
> user-agent, browser-fingerprint, IP (+geo-ip), etc. We could then ask
> that service during a login to calculate the risk involved for that
> login (e.g. geo-distance, same browser, etc). If the IdP decides the
> risk is too high it could enforce multi-factor-authentication.
>
> If we could get enough assurance that the IdP session comes from the
> same user/browser, we could perhaps disable the
> consistentAddress-check, and elevate the authentication level when
> necessary.
>
> Is anyone doing the same thing?
> Are there any existing services out there which we could use?
>
> Kind regards,
>
> Philip
>
>
More information about the users
mailing list