Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for MFA using OIDC conformant endpoints #146

Merged
merged 5 commits into from
May 3, 2018
Merged

Conversation

lbalmaceda
Copy link
Contributor

@lbalmaceda lbalmaceda commented Feb 20, 2018

This PR adds support for the new MFA OTP flow which is mainly based on https://github.com/jaredhanson/draft-oauth-mfa/blob/master/Draft-1.0.txt. It's still missing the association_required error handling (we're blocked) for when the user has not yet enrolled. It also adds javadoc fixes.

The only thing I'm not convinced of is throwing an exception when the new "login with otp" method is called on a non-oidc conformant client. Maybe it's better if we let the request to the server fail and return that error response to the user, WDYT?

Also to be reviewed: Name of the login method, currently loginWithOTP(mfaToken, otp).

Public API changes/additions:

  • On the AuthenticationAPIClient: New method loginWithOTP(@NonNull String mfaToken, @NonNull String otp) to log in sending the mfa-otp grant and the mfa token + otp.
  • On the AuthenticationException: New method isMultifactorTokenInvalid() to evaluate if the error instance corresponds to a "mfa token expired" error.

EDIT: 04/24/18. The association_required error code is meant for the challenge endpoint only, which this SDK is not going to implement.

@cocojoe
Copy link
Member

cocojoe commented Feb 21, 2018

Can you list Public API changes/additions in the first post please.

If you are not convinced of throwing an exception why do it? What is the best experience for the end user who may experience this scenario?

Copy link
Member

@cocojoe cocojoe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general looks good.

* @return a request to configure and start that will yield {@link Credentials}
*/
@SuppressWarnings("WeakerAccess")
public AuthenticationRequest loginWithOTP(@NonNull String mfaToken, @NonNull String otp) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't think of a better name right now but it would be good to be consistent on platforms, In swift the counterpart might be defined as login(withOTP:

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally we can have a single "login" method that just sets the client_id and the path /oauth/token. But then users will need to know for each grant type what parameters are accepted. That's the reason we now have a new login "with otp" method that helps to construct this request.

So in swift what are you doing, is that "withOTP" like a flag?

Copy link
Member

@cocojoe cocojoe Feb 21, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, so in Swift there are 2 login methods one is /ro the other grant password-realm. In this case if I had login(withOTP otp: String, mfaToken: String)

The auto-complete would show 3 logins and it's based on the params, in Swift the guideline is to create methods that have meaninful names. You could have login(otp: String, token: String) which isn't as informative.

When the user calls this method they would write login(withOTP: "12356", mfaToken: "blah") the otp is used inside the method.

}

/// When the MFA Token received on the login request has expired
public boolean isMultifactorTokenExpired() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not the more generic isMultifactorTokenInvalid as an expired token is invalid, does it matter how? You also have {"error":"invalid_grant","error_description":"Malformed mfa_token"}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't catch that error response, probably because I tested it on Lock directly and the token is handled from one endpoint to the other as it is. Yeah it makes sense to handle both cases under the same method, and I agree that in that case it should be named like that -> Invalid.

@cocojoe
Copy link
Member

cocojoe commented Feb 22, 2018

@lbalmaceda Should we mention that you need to enable the MFA grant-type in the README ? Just as we had to mention this for Password?

@lbalmaceda
Copy link
Contributor Author

lbalmaceda commented Feb 22, 2018

@cocojoe Totally. I've updated the PR adding those changes.

}

/// When MFA is required and the user is not enrolled
public boolean isMultifactorEnrollRequired() {
return "a0.mfa_registration_required".equals(code);
return "a0.mfa_registration_required".equals(code) || "unsupported_challenge_type".equals(code);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error is the specific challenge type is not expected vs enrolment in general. Should we clarify this? As it could be they don't support OTP but do OOB?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

association_required will be the new not-enrolled error code once they release the new API, currently this is unsupported_challenge_type. On the other side, "unsupported_challenge_type" does mean that the challenge is not supported. Because we're not going to support other challenge type than OTP, I don't think that's an error we can provide an alternate path to the user to continue the authentication. I tried to find without success, but I think somewhere in the docs they mention that OTP must be supported at least.

Copy link
Member

@cocojoe cocojoe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👌

@cocojoe
Copy link
Member

cocojoe commented May 3, 2018

@lbalmaceda what's codecov complaining about here? Overall project looks fine.

@cocojoe
Copy link
Member

cocojoe commented May 3, 2018

Can probably just lower the patch threshold to say 50%, the project is the most valuable one for me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants