Skip to content

Commit

Permalink
fix(component): make client password and bearer strategy as mandatory (
Browse files Browse the repository at this point in the history
…#210)

make client password strategy mandatory as it needs to be
for any authentication by any strategy.

Also, make bearer stratgey mandatory as everybody use it

GH-209
  • Loading branch information
sf-sahil-jassal committed Jan 17, 2024
1 parent f757e57 commit 13e052e
Show file tree
Hide file tree
Showing 22 changed files with 365 additions and 309 deletions.
2 changes: 0 additions & 2 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,6 @@ Once this is done, you are ready to configure any of the available strategy in t

### Oauth2-client-password

In order to use it, run `npm install passport-oauth2-client-password`.
First, create an AuthClient model implementing the IAuthClient interface. The purpose of this model is to store oauth registered clients for the app in the DB. See sample below.

```ts
Expand Down Expand Up @@ -250,7 +249,6 @@ For accessing the authenticated AuthClient model reference, you can inject the C

### Http-bearer

In order to use it, run `npm install passport-http-bearer`.
First, create a AuthUser model implementing the IAuthUser interface. You can implement the interface in the user model itself. See sample below.

```ts
Expand Down
12 changes: 2 additions & 10 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,6 @@
"type": "./dist/strategies/passport/passport-azure-ad/index.d.ts",
"default": "./dist/strategies/passport/passport-azure-ad/index.js"
},
"./passport-bearer": {
"type": "./dist/strategies/passport/passport-bearer/index.d.ts",
"default": "./dist/strategies/passport/passport-bearer/index.js"
},
"./passport-client-password": {
"type": "./dist/strategies/passport/passport-client-password/index.d.ts",
"default": "./dist/strategies/passport/passport-client-password/index.js"
},
"./passport-cognito-oauth2": {
"type": "./dist/strategies/passport/passport-cognito-oauth2/index.d.ts",
"default": "./dist/strategies/passport/passport-cognito-oauth2/index.js"
Expand Down Expand Up @@ -157,6 +149,8 @@
"https-proxy-agent": "^5.0.0",
"jsonwebtoken": "^9.0.0",
"passport": "^0.6.0",
"passport-http-bearer": "^1.0.1",
"passport-oauth2-client-password": "^0.1.2",
"tslib": "^2.0.0"
},
"devDependencies": {
Expand Down Expand Up @@ -208,11 +202,9 @@
"passport-cognito-oauth2": "^0.1.1",
"passport-facebook": "^3.0.0",
"passport-google-oauth20": "^2.0.0",
"passport-http-bearer": "^1.0.1",
"passport-instagram": "^1.0.0",
"passport-local": "^1.0.0",
"passport-oauth2": "^1.6.1",
"passport-oauth2-client-password": "^0.1.2",
"@exlinc/keycloak-passport": "^1.0.2"
},
"publishConfig": {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
import {Client, createClientForHandler} from '@loopback/testlab';
import {RestServer, Request} from '@loopback/rest';
import {Application, Constructor, Provider} from '@loopback/core';
import {Application, Provider} from '@loopback/core';
import {get} from '@loopback/openapi-v3';
import {Request, RestServer} from '@loopback/rest';
import {Client, createClientForHandler} from '@loopback/testlab';
import AppleStrategy, {DecodedIdToken} from 'passport-apple';
import {authenticate} from '../../../../decorators';
import {STRATEGY} from '../../../../strategy-name.enum';
import {getApp} from '../helpers/helpers';
import {MyAuthenticationSequence} from '../../../fixtures/sequences/authentication.sequence';
import {Strategies} from '../../../../strategies/keys';
import {VerifyFunction} from '../../../../strategies';
import {userWithoutReqObj} from '../../../fixtures/data/bearer-data';
import AppleStrategy, {DecodedIdToken} from 'passport-apple';
import {Strategies} from '../../../../strategies/keys';
import {AppleAuthStrategyFactoryProvider} from '../../../../strategies/passport/passport-apple-oauth2';
import {ClientPasswordVerifyProvider} from '../../../fixtures/providers/passport-client.provider';
import {ClientPasswordStrategyFactoryProvider} from '../../../../strategies/passport/passport-client-password';
import {STRATEGY} from '../../../../strategy-name.enum';
import {userWithoutReqObj} from '../../../fixtures/data/bearer-data';
import {MyAuthenticationSequence} from '../../../fixtures/sequences/authentication.sequence';
import {getApp} from '../helpers/helpers';

describe('getting apple oauth2 strategy with options', () => {
let app: Application;
Expand Down Expand Up @@ -51,12 +49,6 @@ describe('getting apple oauth2 strategy with options', () => {
}

function getAuthVerifier() {
app
.bind(Strategies.Passport.OAUTH2_CLIENT_PASSWORD_VERIFIER)
.toProvider(ClientPasswordVerifyProvider);
app
.bind(Strategies.Passport.CLIENT_PASSWORD_STRATEGY_FACTORY)
.toProvider(ClientPasswordStrategyFactoryProvider);
app
.bind(Strategies.Passport.APPLE_OAUTH2_STRATEGY_FACTORY)
.toProvider(AppleAuthStrategyFactoryProvider);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
import {IAuthUser} from '../../../../types';
import {expect, Client, createClientForHandler} from '@loopback/testlab';
import {RestServer} from '@loopback/rest';
import {Application, inject} from '@loopback/core';
import {get} from '@loopback/openapi-v3';
import {RestServer} from '@loopback/rest';
import {Client, createClientForHandler, expect} from '@loopback/testlab';
import {authenticate} from '../../../../decorators';
import {STRATEGY} from '../../../../strategy-name.enum';
import {getApp} from '../helpers/helpers';
import {MyAuthenticationSequence} from '../../../fixtures/sequences/authentication.sequence';
import {Strategies} from '../../../../strategies/keys';
import {AuthenticationBindings} from '../../../../keys';
import {Strategies} from '../../../../strategies/keys';
import {STRATEGY} from '../../../../strategy-name.enum';
import {IAuthUser} from '../../../../types';
import {BearerTokenVerifyProvider} from '../../../fixtures/providers/bearer-passport.provider';
import {BearerStrategyFactoryProvider} from '../../../../strategies/passport/passport-bearer';
import {ClientPasswordVerifyProvider} from '../../../fixtures/providers/passport-client.provider';
import {ClientPasswordStrategyFactoryProvider} from '../../../../strategies/passport/passport-client-password';
import {MyAuthenticationSequence} from '../../../fixtures/sequences/authentication.sequence';
import {getApp} from '../helpers/helpers';

/**
* Testing overall flow of authentication with bearer strategy
Expand Down Expand Up @@ -242,15 +239,53 @@ describe('Bearer-token strategy', () => {
app
.bind(Strategies.Passport.BEARER_TOKEN_VERIFIER)
.toProvider(BearerTokenVerifyProvider);
app
.bind(Strategies.Passport.BEARER_STRATEGY_FACTORY)
.toProvider(BearerStrategyFactoryProvider);
app
.bind(Strategies.Passport.OAUTH2_CLIENT_PASSWORD_VERIFIER)
.toProvider(ClientPasswordVerifyProvider);
app
.bind(Strategies.Passport.CLIENT_PASSWORD_STRATEGY_FACTORY)
.toProvider(ClientPasswordStrategyFactoryProvider);
}

function givenAuthenticatedSequence() {
// bind user defined sequence
server.sequence(MyAuthenticationSequence);
}
});

describe('integration test when no provider was implemented', () => {
let app: Application;
let server: RestServer;
beforeEach(givenAServer);
beforeEach(givenAuthenticatedSequence);

it('should return error as the verifier is not implemented', async () => {
class BearerNoVerifierController {
constructor(
@inject(AuthenticationBindings.CURRENT_USER) // tslint:disable-next-line: no-shadowed-variable
private readonly user: IAuthUser | undefined,
) {}

options = {
passRequestToCallback: false,
};

@get('/auth/bearer/no-verifier')
@authenticate(STRATEGY.BEARER, {passReqToCallback: false})
async test() {
return this.user;
}
}

app.controller(BearerNoVerifierController);

await whenIMakeRequestTo(server)
.get('/auth/bearer/no-verifier')
.set('Authorization', 'Bearer sometoken')
.expect(401);
});

function whenIMakeRequestTo(restServer: RestServer): Client {
return createClientForHandler(restServer.requestHandler);
}

async function givenAServer() {
app = getApp();
server = await app.getServer(RestServer);
}

function givenAuthenticatedSequence() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
/* eslint-disable @typescript-eslint/naming-convention */

import {IAuthClient} from '../../../../types';
import {Client, createClientForHandler, expect} from '@loopback/testlab';
import {RestServer} from '@loopback/rest';
import {Application, inject} from '@loopback/core';
import {post, requestBody} from '@loopback/openapi-v3';
import {RestServer} from '@loopback/rest';
import {Client, createClientForHandler, expect} from '@loopback/testlab';
import {authenticateClient} from '../../../../decorators';
import {STRATEGY} from '../../../../strategy-name.enum';
import {getApp} from '../helpers/helpers';
import {MyAuthenticationSequence} from '../../../fixtures/sequences/authentication.sequence';
import {Strategies} from '../../../../strategies/keys';
import {AuthenticationBindings} from '../../../../keys';
import {Strategies} from '../../../../strategies/keys';
import {STRATEGY} from '../../../../strategy-name.enum';
import {IAuthClient} from '../../../../types';
import {ClientPasswordVerifyProvider} from '../../../fixtures/providers/passport-client.provider';
import {ClientPasswordStrategyFactoryProvider} from '../../../../strategies/passport/passport-client-password';
import {MyAuthenticationSequence} from '../../../fixtures/sequences/authentication.sequence';
import {getApp} from '../helpers/helpers';

describe('Client-password strategy', () => {
let app: Application;
Expand Down Expand Up @@ -144,9 +143,55 @@ describe('Client-password strategy', () => {
app
.bind(Strategies.Passport.OAUTH2_CLIENT_PASSWORD_VERIFIER)
.toProvider(ClientPasswordVerifyProvider);
app
.bind(Strategies.Passport.CLIENT_PASSWORD_STRATEGY_FACTORY)
.toProvider(ClientPasswordStrategyFactoryProvider);
}

function givenAuthenticatedSequence() {
// bind user defined sequence
server.sequence(MyAuthenticationSequence);
}
});

describe('integration test for client-password and no verifier', () => {
let app: Application;
let server: RestServer;
beforeEach(givenAServer);
beforeEach(givenAuthenticatedSequence);

it('should return status 401 as this strategy is not implemented', async () => {
class TestController {
constructor(
@inject(AuthenticationBindings.CURRENT_CLIENT) // tslint:disable-next-line: no-shadowed-variable
private readonly client: IAuthClient | undefined,
) {}

@post('/test')
@authenticateClient(STRATEGY.CLIENT_PASSWORD, {passReqToCallback: true})
test(
@requestBody()
body: {
client_id: string;
client_secret: string;
},
) {
return this.client;
}
}

app.controller(TestController);

await whenIMakeRequestTo(server)
.post('/test')
.send({client_id: 'some id', client_secret: 'some secret'})
.expect(401);
});

function whenIMakeRequestTo(restServer: RestServer): Client {
return createClientForHandler(restServer.requestHandler);
}

async function givenAServer() {
app = getApp();
server = await app.getServer(RestServer);
}

function givenAuthenticatedSequence() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
import {Client, createClientForHandler} from '@loopback/testlab';
import {RestServer, Request} from '@loopback/rest';
import {Application, Constructor, Provider} from '@loopback/core';
import {Application, Provider} from '@loopback/core';
import {get} from '@loopback/openapi-v3';
import {Request, RestServer} from '@loopback/rest';
import {Client, createClientForHandler} from '@loopback/testlab';
import {authenticate} from '../../../../decorators';
import {STRATEGY} from '../../../../strategy-name.enum';
import {getApp} from '../helpers/helpers';
import {MyAuthenticationSequence} from '../../../fixtures/sequences/authentication.sequence';
import {Strategies} from '../../../../strategies/keys';
import {VerifyFunction} from '../../../../strategies';
import {userWithoutReqObj} from '../../../fixtures/data/bearer-data';
import {Cognito} from '../../../../types';
import {Strategies} from '../../../../strategies/keys';
import {CognitoStrategyFactoryProvider} from '../../../../strategies/passport/passport-cognito-oauth2';
import {ClientPasswordVerifyProvider} from '../../../fixtures/providers/passport-client.provider';
import {ClientPasswordStrategyFactoryProvider} from '../../../../strategies/passport/passport-client-password';
import {STRATEGY} from '../../../../strategy-name.enum';
import {Cognito} from '../../../../types';
import {userWithoutReqObj} from '../../../fixtures/data/bearer-data';
import {MyAuthenticationSequence} from '../../../fixtures/sequences/authentication.sequence';
import {getApp} from '../helpers/helpers';

describe('getting cognito oauth2 strategy with options', () => {
let app: Application;
Expand Down Expand Up @@ -49,12 +47,6 @@ describe('getting cognito oauth2 strategy with options', () => {
}

function getAuthVerifier() {
app
.bind(Strategies.Passport.OAUTH2_CLIENT_PASSWORD_VERIFIER)
.toProvider(ClientPasswordVerifyProvider);
app
.bind(Strategies.Passport.CLIENT_PASSWORD_STRATEGY_FACTORY)
.toProvider(ClientPasswordStrategyFactoryProvider);
app
.bind(Strategies.Passport.COGNITO_OAUTH2_VERIFIER)
.toProvider(CognitoAuthVerifyProvider);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
import {Client, createClientForHandler} from '@loopback/testlab';
import {RestServer, Request} from '@loopback/rest';
import {Application, Constructor, Provider} from '@loopback/core';
import {Application, Provider} from '@loopback/core';
import {get} from '@loopback/openapi-v3';
import {Request, RestServer} from '@loopback/rest';
import {Client, createClientForHandler} from '@loopback/testlab';
import * as GoogleStrategy from 'passport-google-oauth20';
import {authenticate} from '../../../../decorators';
import {STRATEGY} from '../../../../strategy-name.enum';
import {getApp} from '../helpers/helpers';
import {MyAuthenticationSequence} from '../../../fixtures/sequences/authentication.sequence';
import {Strategies} from '../../../../strategies/keys';
import {VerifyFunction} from '../../../../strategies';
import {userWithoutReqObj} from '../../../fixtures/data/bearer-data';
import * as GoogleStrategy from 'passport-google-oauth20';
import {Strategies} from '../../../../strategies/keys';
import {GoogleAuthStrategyFactoryProvider} from '../../../../strategies/passport/passport-google-oauth2';
import {ClientPasswordVerifyProvider} from '../../../fixtures/providers/passport-client.provider';
import {ClientPasswordStrategyFactoryProvider} from '../../../../strategies/passport/passport-client-password';
import {STRATEGY} from '../../../../strategy-name.enum';
import {userWithoutReqObj} from '../../../fixtures/data/bearer-data';
import {MyAuthenticationSequence} from '../../../fixtures/sequences/authentication.sequence';
import {getApp} from '../helpers/helpers';

describe('getting google oauth2 strategy with options', () => {
let app: Application;
Expand Down Expand Up @@ -49,12 +47,6 @@ describe('getting google oauth2 strategy with options', () => {
}

function getAuthVerifier() {
app
.bind(Strategies.Passport.OAUTH2_CLIENT_PASSWORD_VERIFIER)
.toProvider(ClientPasswordVerifyProvider);
app
.bind(Strategies.Passport.CLIENT_PASSWORD_STRATEGY_FACTORY)
.toProvider(ClientPasswordStrategyFactoryProvider);
app
.bind(Strategies.Passport.GOOGLE_OAUTH2_VERIFIER)
.toProvider(GoogleAuthVerifyProvider);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
import {Client, createClientForHandler} from '@loopback/testlab';
import {RestServer, Request} from '@loopback/rest';
import {Application, Constructor, Provider} from '@loopback/core';
import {Application, Provider} from '@loopback/core';
import {get} from '@loopback/openapi-v3';
import {Request, RestServer} from '@loopback/rest';
import {Client, createClientForHandler} from '@loopback/testlab';
import * as InstagramStrategy from 'passport-instagram';
import {authenticate} from '../../../../decorators';
import {STRATEGY} from '../../../../strategy-name.enum';
import {getApp} from '../helpers/helpers';
import {MyAuthenticationSequence} from '../../../fixtures/sequences/authentication.sequence';
import {Strategies} from '../../../../strategies/keys';
import {VerifyCallback, VerifyFunction} from '../../../../strategies';
import {userWithoutReqObj} from '../../../fixtures/data/bearer-data';
import * as InstagramStrategy from 'passport-instagram';
import {Strategies} from '../../../../strategies/keys';
import {InstagramAuthStrategyFactoryProvider} from '../../../../strategies/passport/passport-insta-oauth2';
import {ClientPasswordVerifyProvider} from '../../../fixtures/providers/passport-client.provider';
import {ClientPasswordStrategyFactoryProvider} from '../../../../strategies/passport/passport-client-password';
import {STRATEGY} from '../../../../strategy-name.enum';
import {userWithoutReqObj} from '../../../fixtures/data/bearer-data';
import {MyAuthenticationSequence} from '../../../fixtures/sequences/authentication.sequence';
import {getApp} from '../helpers/helpers';

describe('getting instagram oauth2 strategy with options', () => {
let app: Application;
Expand Down Expand Up @@ -49,12 +47,6 @@ describe('getting instagram oauth2 strategy with options', () => {
}

function getAuthVerifier() {
app
.bind(Strategies.Passport.OAUTH2_CLIENT_PASSWORD_VERIFIER)
.toProvider(ClientPasswordVerifyProvider);
app
.bind(Strategies.Passport.CLIENT_PASSWORD_STRATEGY_FACTORY)
.toProvider(ClientPasswordStrategyFactoryProvider);
app
.bind(Strategies.Passport.INSTAGRAM_OAUTH2_STRATEGY_FACTORY)
.toProvider(InstagramAuthStrategyFactoryProvider);
Expand Down

0 comments on commit 13e052e

Please sign in to comment.