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

Only one strategy allowed in Authentication #2139

Closed
sertal70 opened this issue Dec 10, 2018 · 12 comments
Closed

Only one strategy allowed in Authentication #2139

sertal70 opened this issue Dec 10, 2018 · 12 comments
Assignees

Comments

@sertal70
Copy link

sertal70 commented Dec 10, 2018

Description / Steps to reproduce / Feature proposal

Hi, I'm new to loopback, before opening this issue I tried to find a solution in the issues list or in the google discussion but without success, so here I am.

I'm trying to implement a basic use case for authentication. My scenario is:

  1. client performs a call to /login endpoint passing username and password via a basic http authentication
  2. /login endpoint is decorated with @authenticate('BasicStrategy') so credentials are checked and, if they are ok, the endpoint creates and returns a JWT to the client
  3. client performs a call to /todos/count endpoint sending the JWT in the Auth header (bearer token)
  4. /todos/countis decorated with @authenticate('JwtStrategy') so the JWT token is verified and, if it is ok, the endpoint give back the result to the client

Current Behavior

Everything goes fine until step 4. where I get the error:

Unhandled error in GET /todos/count: 500 The strategy JwtStrategy is not available.

The root cause is in application.ts, where I bind the two strategies for authentication:

    this.bind(AuthenticationBindings.STRATEGY).toProvider(
      JwtAuthStrategyProvider,
    );
    this.bind(AuthenticationBindings.STRATEGY).toProvider(
      BasicHTTPAuthStrategyProvider);

and, as it is clearly stated in the documentation, only one bind is allowed for the same key.

So it seems that the current design of Authentication would not allow more than one strategy at the same time.

For this simple use case it would not be a problem (it is as simple as removing BasicStrategy, because it is used in /login endpoint only and it could be implemented in many different ways).

But what about real production scenarios where multiple strategies should be supported?

Expected Behaviour

In a real, complex project, more than one authentication strategy is often a requirement so IMO it should be supported.

@dhmlau
Copy link
Member

dhmlau commented Jan 24, 2019

@jannyHou , could you please take a look? I think it's related to the authentication work that you're doing. Thanks.

@rohit-khanna
Copy link

Hello @sertal70 ,

I am newbie into LB4 , so apologies if I am talking out of senses ( hehe ).

the below solution could be a workaround, i guess ( i have not tried though),

Let there be a CommonAuthStrategyProvider Class. Assign this Class to the AuthenticationBindings.STRATEGY Key, and then use this:

if (name === 'BasicStrategy') {
      let self = this;
      return new BasicStrategy(this.basicVerify.bind(self));
    } else if (name === 'JWTStrategy') {
      return new JWTStrategy({
        secretOrKey: this.configuration.secrets.jwtSecret,
        jwtFromRequest: ExtractJwt.fromHeader('SOME_HEADER_NAME') // Here extract from headers
      }, this.verifyCallback);
    }

Or Call two separate Auth-Component classes from each of 'if' statements ?

My thought process was: We donot specifiy the Exact Strategy in AuthProviderClass declaration and only create instance when we are sure of what kind of strategy has been decorated on the controller. So insead of exposing multiple auth provider controllers(each specific to one strategy), we can have our MainAuthController which can route/decide on the response.

Please correct me If i misunderstood something.

@sertal70
Copy link
Author

sertal70 commented Feb 1, 2019

Hello @rohit-khanna, thanks for your suggestion and... welcome to the team of LB4 newbie! :)

Theoretically it should work as workaround, I'll give it a try (as soon as I have time) to verify that works and, more important, that there are no side-effects.

@rohit-khanna
Copy link

@sertal70 , glad to be welcomed in the growing team :)
I gave the above solution a shot and it did worked.

I had two endpoints in my controller , one with 'Basic Strategy' and Other one with 'JwtStrategy'. And with the above code i was able to achieve this.

And yes, whenever you have time, you can share your views, this will help us grow..

Cheers :)

@sertal70
Copy link
Author

sertal70 commented Feb 5, 2019

@rohit-khanna I implemented your solution and I can confirm it works, so at least it seems to be a viable workaround until the LB4 team will decide to support more that one auth strategy using the default binding mechanism. Which, IMHO, it should be the preferred way because there is no need to write&mantain a custom auth provider.

@jannyHou
Copy link
Contributor

jannyHou commented Feb 6, 2019

@sertal70 @rohit-khanna The team realized the authentication system should be extensible, story
#2312
and
#2311
are created for allowing people plugin more auth strategies.
Those two stories are our high priorities now.

@rohit-khanna
Copy link

@jannyHou Thats Great. Looking forward to them ! :)
@sertal70 thanks for validation of my workaround :)

@sertal70
Copy link
Author

sertal70 commented Feb 7, 2019

@jannyHou very good news, thanks!

@rohit-khanna thanks to you for the suggestion!

@jannyHou
Copy link
Contributor

jannyHou commented Sep 5, 2019

This feature is supported after having the extension point :)
See the new Authentication component
Especially Registering Custom Auth Strategy

@jannyHou jannyHou closed this as completed Sep 5, 2019
@Swati-GOT
Copy link

Swati-GOT commented Oct 9, 2020

@rohit-khanna It would be great if can u please provide us with some code snippet for this example.
I want to achieve the same thing but somehow I m not able to implement this example.
Will be very thankful you can help me asap

@dhmlau
Copy link
Member

dhmlau commented Oct 9, 2020

@Swati-GOT, did you get a chance to look at the sample snippet in https://loopback.io/doc/en/lb4/Authentication-component-decorator.html#authentication-decorator?

  @authenticate({
    strategy: strategyName1,
    options: {option1: 'value1'}
  }, {
    strategy: strategyName2,
    options: {option2: 'value2'}
  })

@rajkaran
Copy link

@dhmlau @jannyHou I have implemented multiple authetication strategy but they are acting as OR either of them passes endpoint is accessible. Is there a way I can make it AND logic so that both needs to pass.

@authenticate({strategy: 'accesskey', options: {permission: 'write'}}, {strategy: 'jwt'})

If user provides valid access key but invalid jwt token still gets access to the endpoint. I want to prevent it, user should provide valid access key and jwt token to access resources.
Please suggest how can I acheive this?

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

No branches or pull requests

6 participants