websanova / vue-auth

A simple light-weight authentication library for Vue.js
MIT License
2.35k stars 383 forks source link

Handling MFA #684

Open KHIT93 opened 2 years ago

KHIT93 commented 2 years ago

Hi I am working on a project with Vue3, where I need to support MFA. The support is there in the backend application and works like this

I send a request with the following POST data to /auth/login/ on the backend server:

{
    "username": "me@example.com",
    "password": "SecretPassword123#"
}

If no MFA is enabled on the user, we get the authorization token back like this:

{
    "auth_token": "eyJhbGciOiJIUzI1NiIsInR5cCI...AhJA",
}

This is the final token to use and it works fine.

If MFA is enable, the response does change to this:

{
    "ephemeral_token": "1-qrx0ph-e76b858094f0321525b42ad7141b5720816b6a4c",
    "method": "email"
}

The user is then given the MFA code using the defined method and to get the actual auth_token, it is required to send another request to /auth/login/code/ with the following details:

{
    "ephemeral_token": "1-qrx0ph-e76b858094f0321525b42ad7141b5720816b6a4c",
    "code": "925738"
}

Here 925738 is the MFA code and then if my ephemeral_token and code matches with what the backend expects, then I am given the actual token:

{
    "auth_token": "eyJhbGciOiJIUzI1NiIsInR5cCI...AhJA",
}

Currently I handle the custom response key for the token and also the custom header information using a custom authentication driver. I can however not figure out how to get it to work so that the UI can react on the MFA part and then complete authentication.

I was thinking of a method where I send standard axios request to the backend and "log in". If it returns a token, then I call this.$auth.login with the same request data. If it returns the MFA parts, then I handle that myself when the user submits the MFA code, I submit that data, but would need to then override the login URL.

Is there a way to perhaps handle authentication myself and then just let your library finish the process by giving it the actual token?

websanova commented 2 years ago

So if you have the custom driver working and it all ends up with the same auth_token in the end then yes, as you were getting to, it just needs two requests for the login.

I think like this:

this.$auth.login({
    body: {email: 'email', pass: 'pass'},
    fetchUser: false
})
.then(() => {
    // If MFA so do the other request
    if ( do MFA) {
        // Do MFA request
        // If a token comes back it should get picked up automagically by the plugin.
        this.$http(....)
        .then(() => {
             this.$auth.fetch();
        })
    }

    // Else nothing happens, you already got the token.
    this.$auth.fetch();
})

Keep in mind the $auth.login() is just doing an http request, it's literally just a wrapper.

However not sure with the remember me if you're using that, so might require checking into the login call a bit more if that's needed.