Giter Club home page Giter Club logo

moodle-tool_mfa's Introduction

moodle-tool_mfa

What is this?

This is a Moodle plugin which adds Multi-Factor authentication (MFA), also known as Two-factor authentication (2FA) on top of your existing chosen authentication plugins.

https://en.wikipedia.org/wiki/Multi-factor_authentication

Why another MFA plugin for Moodle?

There are other 2FA plugins for moodle such as:

https://moodle.org/plugins/auth_a2fa

This one is different because it is NOT a Moodle authentication plugin. It leverages new API's that Catalyst specifically implemented in Moodle Core to enable plugins to augment the login process instead of replacing it. This means that this MFA plugin can be added on top of any other authentication plugin resulting in a much cleaner architecture, and it means you can compose a solution that does everything you need instead of compromising by swapping out the entire login flow.

See this tracker and the dev docs for more info:

https://tracker.moodle.org/browse/MDL-66173

https://docs.moodle.org/dev/Login_callbacks

The other major difference is that we support multiple authentication factor types as sub plugins, e.g. SMS, IP Range, Email, TOTP and WebAuthn / FIDO2 and in future anything else as new sub-plugins. They can be flexible configured so that different combinations of factors are considered enough.

Moodle supported branches

Version Branch Required patches
Moodle 4.0 - 4.2 MOODLE_400_STABLE None
Moodle 3.8 -3.9 MOODLE_35_STABLE None
Moodle 3.7 MOODLE_35_STABLE MDL-66340
Moodle 3.5-3.6 MOODLE_35_STABLE MDL-66340, MDL-60470

Totara supported branches

Version Branch Required patches
Totara 12-17 TOTARA_12 MDL-66340, MDL-60470
Totara 18 TOTARA_18 MDL-66340, MDL-60470

Installation

Step 1: Install the local module

Using git submodule:

git submodule add [email protected]:catalyst/moodle-tool_mfa.git admin/tool/mfa

OR you can download as a zip from github

https://github.com/catalyst/moodle-tool_mfa/archive/master.zip

Extract this into /var/www/yourmoodle/admin/tool/mfa/

Then run the moodle upgrade as normal.

https://docs.moodle.org/en/Installing_plugins

Step 2: Apply core patches

This plugin requires MDL-60470 which was only added in 3.7, and MDL-66340, which was added in 3.8.

You can easily backport these patches in one line for 3.5, 3.6 and 3.7:

For Moodle 3.5:

git am --whitespace=nowarn < admin/tool/mfa/patch/core35.diff

For Moodle 3.6:

git am --whitespace=nowarn < admin/tool/mfa/patch/core36.diff

For Moodle 3.7:

git am --whitespace=nowarn < admin/tool/mfa/patch/core37.diff

Manual cherry-pick

In case the patches do not work due to an update to older Moodle branches (such as security updates), you can manually perform the cherry-picks. For MDL-60470:

git cherry-pick bf9f255523e5f8feb7cb39067475389ba260ff4e

If there are merge conflicts, ensure the lines that you are adding are consistent with the lines being added inside the patch files. Everything else can safely be ignored.

For MDL-66340:

git cherry-pick 4ed105a9fd4c37e063d384ff155bd10c3bfbb303

As with above, if there are merge conflicts, ensure the lines that you are adding are consistent with the lines being added inside the patch files. Everything else can safely be ignored.

Once this has been performed, you can generate your own patch files using git format-patch. An example for Moodle 3.5 is below:

git format-patch MOODLE_35_STABLE --stdout > admin/tool/mfa/patch/new_core35.diff

Configuration

WARNING: Do not try to fully configure this plugin in the web GUI immediately after installation, at this point during the upgrade process you are not actually logged in so it is easy to 'brick' your moodle and lock yourself out.

The main concept to understand is the concept of factors. Each user must satisfy some combination of factors which sum to 100 points in order to login. By configuring multiple factors and weighting them you can easily have quite complex and flexible rules.

Authentication factors

These are what you would consider 'normal' 2FA or MFA factors.

TOTP

This is standard Time-base One Time Password (TOTP) using Google Authenticator, Authy, Duo or any other app which conforms to the open standard.

Mobile SMS

Send One Time security codes to mobile via SMS using AWS SNS.

WebAuthn / FIDO2

With FIDO Authentication, users sign in with phishing resistant credentials, called passkeys. Passkeys can be stored on devices, like smartphones or hardware security keys, and enable password-only logins to be replaced with secure and fast login experiences across websites and apps.

The WebAuthn / FIDO2 factor has been tested with the Swissbit iShield Key series and Yubico products. Other FIDO2 certified security keys should also be compatible with this plugin.

IP Range

Use this factor to say that if you are on a secure network then that counts for something. This is very useful because it requires no setup by the end user, so you can set it up so that you can login fully via a secure network, and once logged in they can setup other factors like TOTP, and then use those other factors for logging in when not on a secure network.

Email

A simple factor which sends a short lived code to your email which you then need to enter to login. Generally speaking this is a low security factor because typically the same username and password which logs you into moodle is the same which logs you into your email so it doesn't add much value.

This factor was implemented as a proof of concept of a factor which can return a hard FAIL state, ie positive evidence that your account is compromised rather than NEUTRAL where we simply lack evidence of additional factors that the end user is who they say they are.

Lockout threshold

This is a generic setting which applies to all the 'input' factors above which is the amount of attempts a user has at answering input factors before they are not permitted to login. If your account is locked there is an admin report to find and unlock these users.

User filtering factors

These are pseudo factors which make it easier to setup policies around who MFA should apply to or not.

Auth Type

This is so you can specify that users with certain auth types, eg SAML via ADFS, which may have already done it's own MFA checks, is worth 100 points which makes it exempt from additional checks.

Non-admin

This factor enables you to give points for free to a user who is not an admin. This makes it easy to require admin users to have 2 or more factors while not affecting normal users.

User capability

This factor checks whether a user has a capability, in the system context. If the user has this capability, they will not gain the points for this factor, and must instead use other factors to authenticate with the system. This is similar to the non-admin factor, however it operates on a role basis. In practice, the capability 'factor/capability:cannotpassfactor' should be given to roles who must use other factors to authenticate to the system. There is an additional setting for this factor, that will allow admins to gain points for this factor, as by default they will always gain no points for this factor.

Role Factor

This factor checks whether a user has any chosen roles assigned in any context, and does not provide points if so. This can be used to ensure the selected roles must use a higher level of authentication such as TOTP, while letting non-specified roles authenticate seamlessly. This factor should generally have high privilege roles such as Manager and Administrator selected to enforce higher account security for these groups.

Login banner Factor

This factor allows for display of a policy which forces users to read and accept a policy on every login. This is more flexible than the Moodle policy tool, which is built for one time acceptance. To set the message, a custom language pack should be used to override factor_loginbanner/policytext. This means that it can be replaced with an arbitrary set of HTML to display to the users. This factor should be used with a weight of 0 if you wish it to be an additional layer over the top of the MFA flow, without contributing any weight.

Login flow factors

These pseudo factors affect the overall setup flow for users.

Grace mode

The grace mode is a pseudo factor to allow users to log in without interacting with MFA for a set period of time. Users can only achieve the points for this factor if there are no other input factors for them to interact with during the login process. This factor should be placed last in the list, that way all other factors are interacted with during the login process first. On the first page after login, if a user is currently within their grace period, regardless of whether they used gracemode as a login factor, they are presented a notification informing them of the grace period length, and that they may need to setup other factors or risk being locked out once the grace period expires.

No-setup Factor

This pseudo factor is designed to allow people to pass only if they have not setup other factors for MFA already. Once another factor, such as TOTP is setup for a user, this factor no longer gives points, therefore the user must use TOTP to authenticate. This allows for an optional MFA rollout, where only users who wish to use MFA are affected by the MFA rollout.

Security Questions

Another Catalyst plugin is the Security Questions plugin which augments the password reset process to be based off questions specific to the user rather than only access to the users email.

There is a Security Questions factor, BUT this is only because both plugins use the same callbacks and clash so this factor makes the two plugins compatible with each other.

It is possible that this factor could be turned into a proper factor which accepts answers to these questions if no other factors can be used.

https://github.com/catalyst/moodle-tool_securityquestions

Other factors

In theory you could impement almost anything as a factor, such as time of day, retina scans, or push notificatons. For a list of potential factor ideas see:

https://en.wikipedia.org/wiki/Multi-factor_authentication#Authentication_factors

Moodle Mobile App

By default the Moodle Mobile app handles the authentication of users directly, which circumvents the steps that tool_mfa adds.

To enforce MFA for the app as well you must set the tool_mobile 'typeoflogin' admin setting to be 'Via a browser window'.

Points and examples

If a users cumulative points is high enough then they are able to login. Points can be weighted for different factors. Some factors do not require any input, such as checking their IP Address is inside secure subnet, while other factors require input such as entering a code like TOTP or SMS. Factors with no input are checked first and then the remaining factors are checked in from the largest points to the smaller until you either have a cumulative points high enough to login, or you run out of factors and you are denied login.

When you configure the points in the admin settings it will generate a list of valid factor permutations to easily check it's configured the way you want.

Example 1

If you have 3 factors configured, all factors default to 100 points effectiely making any of then enough to login:

auth=saml => 100
iprange => 100
totp => 100

Then it will show:

You must be:
* has an authentication type of saml
OR
* is on a secured network
OR
* using a TOTP app

Example 2

If you change all 3 points to 50 then it would say:

You must be:
* has an authentication type of saml AND is on a secured network
OR
* has an authentication type of saml AND using a TOTP app
OR
* is on a secured network AND using a TOTP app

Example 3

With a configuration of:

auth_saml => 100
iprange => 100
totp => 100
email => 50
security_quesstions => 50

Then these are valid conditions:

You must be:
* has an authentication type of saml
OR
* is on a secured network
OR
* using a TOTP app
OR
* has valid email setup AND answers security questions

Debugging

While you are setting up MFA there are 2 things which help make it simple to see what is going on:

  1. In the settings page is a 'Summary of good conditions for login' which does what it says on the box. If you have not setup any factors, or if they are configured in a way which would never all login then it will warn you.

  2. You can turn on debug mode, when you are logging in and stepping through the MFA login flow if will show you the list of factors and how they have been resolved. This is also shown on the MFA user settings page after you have logged in showing what combination was used for you session.

If you have inadvertantly messed things up and locked yourself out, you can disable the whole MFA plugin from the CLI:

php admin/cli/cfg.php --component=tool_mfa --name=enabled --set=0

Security issues

If you find a security issue with this or any catalyst plugin, please DO NOT open a github issue.

Instead please responsibly disclose the issue in private to us via email:

[email protected]

Support

If you have issues please log them in github here

https://github.com/catalyst/moodle-tool_mfa/issues

Please note our time is limited, so if you need urgent support or want to sponsor a new feature then please contact Catalyst IT Australia:

https://www.catalyst-au.net/contact-us

This plugin was developed by Catalyst IT Australia:

https://www.catalyst-au.net/

Catalyst IT

Warm thanks

Thanks to the various authors and contributors to this plugin!

Thanks to Swissbit for sponsoring the work to add WebAuthn / FIDO2 support to this plugin.

moodle-tool_mfa's People

Contributors

alexmorrisnz avatar alphadijkstra avatar andrewnicols avatar brendanheywood avatar bwalkerl avatar chrispratt-tonyyeb avatar danmarsden avatar dmitriim avatar dryj avatar golenkovm avatar jackson-catalyst avatar keevan avatar liamkearn avatar matthewhilton avatar nhoobin avatar nomisge avatar owenherbert avatar peterburnett avatar scottverbeek avatar tomotsuyuki avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

moodle-tool_mfa's Issues

Warn when you may not have enough points from factors which require setup

Lets say there are some factors which require user setup, eg totp or duo. And there are other factors which don't require user intervention like iprange.

Now lets say they login, on a secure network, so they come through fine. But if they were not on a secure network they would be locked out completely. So they need to be alerted to setup the factors to allow them to login from outside the network, but in a generic way regardles of the factors involved.

So lets say there are 4 factors enabled, each with 50 points, and 2 require setup. So we have 100 points of 'no setup' factors and 100 points of 'setup required' factors.

So when you are logged in, regardless of how you logged in, check how factors they have setup, and if the total of those is less than 100 then warn them and punt them off to the user prefs page.

The most typical setup for this would be iprange = 100 + totp = 100

Now when it does actually warn you, it should build up the warning text based on the non-setup factors, eg if the first factor is iprange, then it should say 'If you are not on a trusted network' then you won't be allowed to login without additional factors setup. This will depend on lot of the weightings and the ordering of factors, so we can side step a lot of the complexity with careful language, eg 'you need additional factors' rather than 'you need 2 more factors' - because we don't know which combinations are enough yet, so you just prompt them to add one, and then re-check, and then maybe add more.

Have a 'trust this device' option on auth page

This might share some code with a 'recent devices' factor:

#15

Broadly we'd record some sort of fingerprint for a device, maybe a long lived cookie, + the user agent, and possible also combined with a ip address, and allow people to trust it.

image

The admins might be able to say things like only allow people to trust devices on a certain network.

Add recent login email + notification

If you have been logged in on this device before then that counts for something rather than being on a completely unknown device.

This could work by storing and comparing moodle old session id's or previous ip addresses or some combination.

We probably need a after_login method for factors as we only want to store things when we know we've gotten all the way through MFA. And in this method for this factor we'd store the new ip or session cookie value ourselves in user prefs and manage it directly.

Have settings for whether MFA should be 'optional,suggested, enforced, grace period'

There will be 2 settings in the MFA setup: a grace mode, and a grace duration

These are all what affects what happens when you attempt to login, but do not have any factors setup.

Grade mode:

  • optional, it's just on your preferences page but no prompts

MFA is totally optional, if you choose to set it up, and only if you have set it up, will you account then be required to use MFA to login.

This is almost the same as just being off. This needs some thought around how to handle and detect when you've cancelled a totp input request for example.

  • suggested, when you login add a notification

When you login, a notification will be added to your session. So when you end up at your wants url you'll get an info box saying 'please add mfa' with a link

  • enforced, when you login you redirect to the setup page won't do

If you attempt to go to any other page you MUST be either served a redirect back to the setup page OR you will be served an error page for situations where you'd end up in a redirect loop.

  • graceful, same as above but can be dismissed, but only for a certain period eg 2 weeks. Nice workaround so if you must login for say an exam you can get the job done and come back to it

Move wants url logic from query param to session var

Make sure this work with a wants url set from the login process so don't overwrite it

A test scenario:

  • deep link to a course

  • login, and purposefully get the password wrong once or twice then login

  • test in grace mode, should go to preferences page, do some stuff, then at the end you should see a 'go to URL' link at the bottom of your settings

  • Rinse and repeat, but in login mode when you have mfa setup, test it with say 2 factors requiring input, or test it and get the verification wrong a couple times and then right

Have an 'email' factor

  • has_setup() = false
  • is_ready() = do they have an email, and validate_email() + over_bounce_threshold()
  • login flow, sends as email with a code, you copy the code into the login form.
  • the email also ha the ip address and UA and anything else handy that might help identify the malicious user
  • would usually be very low priority, eg last in the list
  • the email should also have a 'This wasn't me' link. The one upside of this approach is that even if your email was compromised you might still see the email. If you do then you can click on the link and it will:
    • work even if you yourself are not logged in (ie you were just doing something else and saw it, it's obviously not you, you need to mitigate it ASAP, and your moodle account may be compromised so you can't actually log in anyway)
    • invalidate the code so the malicious person can't use it
    • even if they had used that code and logged in, when you click that link it will log them out remotely.
    • log an event with details of the ip address, browser UA and anything else
    • perhaps suspend your account until you can look into it more (needs an option for this)

This still isn't perfect as the person checking your email could also delete the email.

To cleanly do this, a factor can also return a state of 'hard fail' in addition to either a 'yes' (ie yes I'm in the ip range), a no (I'm not in the ip range but thats ok). If any factor returns a fail then the login flow is instantly over.

TOTP factor login flow form should be very smooth UX

  • render a big chunky form which has just the 6 digit codes nice and big
  • auto focus the form
  • if you have entered 6 digits then immediately fire off an ajax request to test it, if it is good then redirect right away. If not mark it as red

GA app overwrites existing account with the same name

I noticed a GA app bug/feature.
It silently overwrites existing account if you feed it by a new one with the same name.

ie when you generate qrcode using first secret code with a uri like this:
'otpauth://totp/mike:[email protected]?secret=FIRSTSECRETCODE&issuer=Moodle'
GA app creates an account with name "Moodle (mike:[email protected])". Then we store factor with FIRSTSECRETCODE in db.

When you decide to add one more factor you click Add totp factor we draw a new qr code with new secret code with uri like this:
'otpauth://totp/mike:[email protected]?secret=SECONDSECRETCODE&issuer=Moodle'

If you scan this qr code with a new device - GA app will just create an account "Moodle (mike:[email protected])" as usual.

However, if you (intentionally or unintentionally) scan it with you first device that already has this account,
GA app will silently overwrites the first one.

So, finally, you will have only one "Moodle (mike:[email protected])" account on your device. Second one.
And the first one will be permanently lost.

Pobably it's not critical, but we will have active orphaned totp factor in user profile that is never used again.

For higher level of security allow override / removal of the domain and username in TOTP qr codes

https://medium.com/crypto-punks/why-you-shouldnt-scan-two-factor-authentication-qr-codes-e2a44876a524

tl;dr: If your phone is compromised a hacker now knows your username, and the domain, and the totp key and only lacks the password. By removing the domain, username, or both from the qr code it's less info on the device. I think this is relatively low because if your device is both lost AND compromised, then they'll likely have your email password and various other things too. If you lose your device you just want to revoke the totp codes asap.

Have an 'iprange' factor

eg you can only set a new TOPT on the cat network the first time you set it up.

  • have admin setting , there is an ip range

address_in_subnet(getremoteaddr()

remoteip_in_list()

refactor the good / bad/ neutral into a share get / set with class constants

  • unknown, we have not tested it yet (which may require doing something like sending an email, and may alsy require checking something like veryfiny a token)
  • pass - verified
  • neutral - not verified - generally a no result is not negative, you simply may not have your phone
  • bad - positive information that something bad is going on. eg you got an email saying please confirm this code, when it wasn't you. You can click a link saying 'nope it wasn't me!' see #12
  • need a set_state() too

Touch points:

https://github.com/catalyst/moodle-tool_mfa/blob/master/lib.php#L165-L166

https://github.com/catalyst/moodle-tool_mfa/blob/master/auth.php#L72-L77

On the mfa plugin manage page show a summary of good conditions for login

  • when this is loaded or saved show a summary table which lists the conditions based on the scores and priority.
  • have help text which says you probably want the factors with the highest score listed first.

eg if you require a score of 100 and you have:

auth,saml => 100
iprange => 100
totp => 100

The it will show:

You must be:
* logged in via saml
OR
* on a secure network
OR
* use TOTP

If you then change the 3 scores to 50 then it would say:

You must be:
* logged in via saml AND on a secure network
OR
* logged in via saml AND use TOTP
OR
* on a secure network AND use TOTP

Have special handling of admin "login as" functionality

ie if you are an admin logged in as someone else then you should be able to do some things, like revoke a key, but you should not be able to setup a new key. Needs some thought here

  • first you can't actually login at all if they have totp setup (it's kinda doing it's job!). Business decision around bypassing this?? Another setting?

If you can't login, and there is no grace, and there is 'no setup factors' then explain them

This is the reverse case of: #54

Lets say we have a hard line policy of iprange OR totp and no grace. So you must login on a secure network, setup totp, to enable use in the wild.

Lets say a user doesn't do that, they are outside, they will just be denied access. Now we could just have a generic 'you don't have enough factors' message, but it's not that great. We could allow it to be overridden, and thats ok but it's extra work.

Instead we should generate a 'possibly way to login' if one exists. ie lets assume they have 0 points of 'needs setup' factors, but there is 100 points of 'no setup' factors. Then it should say 'if you want to login, you need to be on a secure network, and then you can setup MFA'

Maybe we can structure it so we can use the same chunks of language for both use cases (but might get awkward quickly)

For totp show for each device when the code was last verified

The last modified date probably has little value in it's own right as most factors don't really have a meaningful 'edit' concept'. So I'd just reuse this field and update the record every time it is validated.

When editing a totp record for the purposes of renaming a device, it probably makes sense to enforce them reconfirming the code for that specific device too, so the last mod field is serving double duty without needing two fields.

Have a push notification factor using duo

Of the various push notification based services out there this seems like one with a lot of traction and an easy api

https://duo.com/product/trusted-users/two-factor-authentication/authentication-methods/duo-push

also free for 10 users which makes it easy to develop, and even use in prod if limited to say just a small group of admins

https://duo.com/pricing

https://github.com/duosecurity/duo_api_php

Add totp factor ui polish

  • the form should be in the order you do this so:
  1. Enter the name of your device eg 'Brendan's work iPhone' <-- update the lang strings for this

  2. Enter the security code OR scan the qr code, move this up into the form

  3. then enter the code

  • the crumb trail is missing from this page, should have a node for the MFA page and for the add factor page

Have a 'factor' sub plugin type

  • factors have a priority / order. I'm thinking for simplicity this is declared by the plugin and cannot be changed. Some factors which have no login flow like ip would be ordered at first.
  • factors have a score. This could default to 1, but we able to override this
  • you will have a global 'must have X score' in order to login
  • each factor should have a method needs_setup()
  • have a admin setting which renders a table to manage all the plugins, when each is enabled, the score, the priority.
  • have an auto loaded form:
class /factor/plugin/classes/forms/login.php - for login flow (eg enter your qr code)
class /factor/plugin/classes/forms/setup.php - for setup flow (eg generate a code)

When you turn it on you can say 'you need at least X made up of other factors to login', ie an ip factor is 1, and totp with worth 1, and you need 1 to login.

  • when you login lets say via an ip network, we need to know that you must now also setup other factors. The 'ip' one has not setup. But the totp on does, so you need to be ask to set it up so that you can come back later when not on the corporate ip network.

Have an 'is admin' factor so admins can be penalized and need more other factors to make up for it

This might seem weird, but it would make it very easy to have policies like 'if you are are admin then your factor points need to be higher'. We achieve this by having a negative points for this factor. This also means that this factor needs to be evaluate first. The simplest is to run all negative point factors first, or if we really need it then add an explicit priority / order column to the factors.

Ability for factors to not require input

Some factors, such as auth_type or ip-range do not require input from the user to be a pass or fail. These should have a way to just query the success or failure from the class.

Inside the object_factor_base class and interface, implement new methods to query whether the factor requires user input for verification, and the result of factor:

  • has_input()
  • get_state() #56

This can then be checked during login flow:

  • if has_input() -> display form else get_state -> pass/fail factor

MVP for topt login flow

  • on a new login, after login redirect them to a topt setup page, store the wants url
  • render a qr code, they scan it. There is a QR code library inside code
require_once($CFG->libdir.'/tcpdf/tcpdf_barcodes_2d.php');
$barcode = new TCPDF2DBarcode($qrcodeurl, 'QRCODE');
$image = $barcode->getBarcodePngData(15, 15);
echo html_writer::img('data:image/png;base64,' . base64_encode($image),''));
  • there needs to be the ability to have multiple topt per account. Each will have a name

  • then they type in the topt to prove that they scanned it and then they get logged in. Log an event for this.

  • if they try to go elsewhere then they get redirected back (possibly with a grade period we can add later)

  • on subsequent logins they get the topt prompt, and enter it and that is stored in the session

  • after either code setup, or code entering, redirect to the wants url

MVP for subplugin based MFA

  • first determine resolve all of the no-input factors such as iprange
  • now if we still don't have enough points work down the list of factors in turn
  • trigger each factors once, this will send an email, or send a test etc. TOTP doesn't need this.
  • then render the factors login flow form eg /topt/classes/forms/login
  • each factor is responsible for managing its state and mutating and resolving it's state. ie if the user submits the form, and the code is correct then change the state to 'Yes'. If they didn't receive the code and want to skip this factor then it resolves to 'No'
  • now control passes back to the main plugin, and it moves to the next plugin down the line.
  • if we have enough points then we mark this in the session and the user goes on their way
  • if we run out of factors then we send an error message and log them out
  • if we time out then we log them out
  • if at any time any single factor resolves to fail then we log them out

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.