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

Feat/Auth : refreshToken request automatically sent by NbAuthService if isAuthenticatedOrRefresh is called #649

Merged
merged 58 commits into from
Aug 22, 2018

Conversation

alain-charles
Copy link
Contributor

@alain-charles alain-charles commented Aug 18, 2018

Feat/Auth :

  • refreshToken request automatically sent by NbAuthService if isAuthenticatedOrRefresh() is called
  • NbAuthJWTInterceptor now calls NbAuthService.isAuthenticatedOrRefresh()

POTENTIAL BREAKING CHANGE if NbAuthJWTInterceptor is used :
The developper has now to provide in his auth_module a function filterInterceptorRequest(req: HttpRequest<any>):boolean that returns true if req.url must not be intercepted for bearer token injection.
The auth urls MUST be included there.

export function filterInterceptorRequest(req: HttpRequest<any>) {
  return ['http:https://localhost:4400/api/auth/',
              'http:https://other.url/with/no/token/injected/',
         ]
    .some(url => req.url.includes(url));
}
....
{ provide: NB_AUTH_TOKEN_INTERCEPTOR_FILTER, useValue: filterInterceptorRequest},

Playground sample follows.

alain-charles and others added 30 commits June 29, 2018 08:33
Now : If existing, NbAuthResult contains backend error description
other Changes requested by Dmitry (first review)
Now : If existing, NbAuthResult contains backend error description
other Changes requested by Dmitry (first review)
+tslint missing trailing comma arghhh
…strategy

 used to create the token (future use)
The token now contains ownerStrategyName, with is a back link to the strategy
used to create the token (future use).

BREAKING CHANGE :
NbAuthCreateToken (token.ts) now takes a third parameter, which is the ownerStrategyName
Tokens are created by strategies that are called from services, so it is *potentially* a breaking change.
The token now contains ownerStrategyName, with is a back link to the strategy
used to create the token (future use).
updated unit tests files and oauth2-password-login.component (breaking change below)

BREAKING CHANGE :
NbAuthCreateToken (token.ts) now takes a third parameter, which is the ownerStrategyName
Tokens are created by strategies that are called from services, so it is *potentially* a breaking change.
removed useless code and cleaned one unit test file

BREAKING CHANGE :
NbAuthCreateToken (token.ts) now takes a third parameter, which is the ownerStrategyName
Tokens are created by strategies that are called from services, so it is *potentially* a breaking change.
nnixaa and others added 17 commits July 25, 2018 15:03
Tokens can now be asked for their creation date via createdAt attribute or getCreatedAt()
NbAuthOAuth2Token.getTokenExpDate() now returns a correct expDate (Issue #564)

Unit tests updated

nnixaa first review
Tokens can now be asked for their creation date via createdAt attribute or getCreatedAt()
NbAuthOAuth2Token.getTokenExpDate() now returns a correct expDate (Issue #564)

Unit tests updated

nnixaa first review
nnixaa second review
Tokens can now be asked for their creation date via createdAt attribute or getCreatedAt()
NbAuthOAuth2Token.getTokenExpDate() now returns a correct expDate (Issue #564)

Unit tests updated

nnixaa first review
nnixaa second review
removed attributes declaration overriding in NbAuthOauth2Token constructor
Tokens can now be asked for their creation date via createdAt attribute or getCreatedAt()
NbAuthOAuth2Token.getTokenExpDate() now returns a correct expDate (Issue #564)

Unit tests updated

nnixaa first review
nnixaa second review
nnixaa third review (am i so bad ? :-p)
A new class of token has been defined.
NbAuthOAuth2JWTToken : class to use when your auth backend sends Oauth tokens encapsulating a jwt access token.
# Conflicts:
#	src/framework/auth/services/token/token.ts

Optimized token.ts code
# Conflicts:
#	src/framework/auth/services/token/token.ts

Optimized token.ts code
@codecov
Copy link

codecov bot commented Aug 19, 2018

Codecov Report

Merging #649 into master will increase coverage by 0.29%.
The diff coverage is 96.15%.

@@            Coverage Diff             @@
##           master     #649      +/-   ##
==========================================
+ Coverage   72.44%   72.74%   +0.29%     
==========================================
  Files         153      154       +1     
  Lines        4272     4296      +24     
  Branches      330      333       +3     
==========================================
+ Hits         3095     3125      +30     
+ Misses       1113     1107       -6     
  Partials       64       64
Impacted Files Coverage Δ
...work/auth/services/interceptors/jwt-interceptor.ts 100% <100%> (+50%) ⬆️
src/framework/auth/auth.options.ts 100% <100%> (ø) ⬆️
src/framework/auth/services/auth.service.ts 91.07% <100%> (+1.48%) ⬆️
src/framework/auth/auth.module.ts 84.61% <66.66%> (-1.88%) ⬇️
src/framework/auth/components/index.ts 100% <0%> (ø)

)
} else {
return observableOf(token.isValid());
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

just an unnecessary space

@@ -24,7 +24,7 @@ describe('auth-service', () => {
let tokenService: NbTokenService;
let dummyAuthStrategy: NbDummyAuthStrategy;
const testTokenValue = 'test-token';
const ownerStrategyName = 'strategy';
const ownerStrategyName = 'dummy';
Copy link
Collaborator

Choose a reason for hiding this comment

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

do we need this change? looks unrelated

Copy link
Contributor Author

@alain-charles alain-charles Aug 20, 2018

Choose a reason for hiding this comment

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

Yes we do since i added isAuthenticatedOrRefresh() calls in the unit tests
The strategy provided in test module is named 'dummy'.
So i modified the ownerStrategyName to dummy and replaced all 'dummy' occurrences by ownerStrategyName.
I know everything is not related to this PR, but is was necessary.

@@ -60,7 +60,6 @@ export function nbStrategiesFactory(options: NbAuthOptions, injector: Injector):
.forEach(([strategyClass, strategyOptions]: [NbAuthStrategyClass, NbAuthStrategyOptions]) => {
const strategy: NbAuthStrategy = injector.get(strategyClass);
strategy.setOptions(strategyOptions);

Copy link
Collaborator

Choose a reason for hiding this comment

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

do we need this change? looks unrelated

Copy link
Contributor Author

Choose a reason for hiding this comment

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

OK i put on back the empty line :)

import { NbAuthService } from '../auth.service';
import { NbAuthJWTToken } from '../token/token';
import { NB_AUTH_TOKEN_INTERCEPTOR_FILTER} from '../../auth.options';
Copy link
Collaborator

Choose a reason for hiding this comment

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

space

switchMap(authenticated => {
if (authenticated) {
return this.authService.getToken().pipe(
switchMap( (token: NbAuthToken) => {
Copy link
Collaborator

Choose a reason for hiding this comment

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

space

Copy link
Collaborator

Choose a reason for hiding this comment

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

@alain-charles just one last formatting issue here :)
switchMap( (token: NbAuthToken) => { -> switchMap((token: NbAuthToken) => {

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 run npm lint before I push but it seems my config is not as restrictive as yours .
Which one do you use ?

Copy link
Collaborator

Choose a reason for hiding this comment

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

It looks like the project lint config isn't the best one. Will look into it.

}

protected get authService(): NbAuthService {
return this.injector.get(NbAuthService);
}

protected get filter(): (req: HttpRequest<any>) => boolean {
return this.injector.get(NB_AUTH_TOKEN_INTERCEPTOR_FILTER);
Copy link
Collaborator

Choose a reason for hiding this comment

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

I guess the token can be injected using constructor (except for AuthService)

}



Copy link
Collaborator

Choose a reason for hiding this comment

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

couple of unnecessary new lines

switchMap(authenticated => {
if (authenticated) {
return this.authService.getToken().pipe(
switchMap( (token: NbAuthToken) => {
Copy link
Collaborator

Choose a reason for hiding this comment

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

@alain-charles just one last formatting issue here :)
switchMap( (token: NbAuthToken) => { -> switchMap((token: NbAuthToken) => {

@nnixaa
Copy link
Collaborator

nnixaa commented Aug 21, 2018

@alain-charles I just noticed that we don't provide a default value for the filter right? Meaning that if we try to use the interceptor without providing a filter it will fail by calling this.filter() right?

We can provide a noop filter, so a simple () => true function

@alain-charles
Copy link
Contributor Author

No we don’t.
That is he potential breaking change I am talking about in the PR Desc.
I agree we should provide a no op filter.
I’ll push very soon

Returns always true so that NO url is intercepted
=> the user writes the filter according to the doc (Auth urls MUST be filtered) and injects it in his own auth_module
.pipe(
switchMap(token => {
if (!token.isValid()) {
return this.refreshToken(token.getOwnerStrategyName(), token)
Copy link

@cloakedch cloakedch Aug 22, 2018

Choose a reason for hiding this comment

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

Does this work with any kind of token type? Is the refreshToken endpoint always expecting the same token that was stored?

I am using an API that during authentication returns an object consisting of a refresh token, an access token and other properties. However, on refreshing the token I am expected to only supply the refresh token.
To get it working, I had to convert the token to an NbAuthOAuth2Token and explicitly call "oAuth2Token.getRefreshToken()" on this line instead of just "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.

Hi @cloakedch ,

The refresh_token is implemented according to RFC6749 section 1.5.

This RFC specifies the OAuth2 authentication scheme. So the code works with auths server returning tokens according to the RFC section 4.2
The refreshToken endpoint is waiting for the refresh_token that was sent during login or during the latest refresh_token call. Both grant_type=refresh_token and refresh_token=theRefreshToken are sent to the refreshToken endpoint for getting a new access-token, according to the RFC.

I would say that you have to use the NbOAuth2AuthStrategy with password grantType(if you send login/password at login) and NbAuthOAuth2Tokenclass in your case.

Someting like

            NbOAuth2AuthStrategy.setup({
          name: 'password',
          clientId: 'test',
          clientSecret: 'secret',
          baseEndpoint: 'http:https://your.BaseEnd/Point',
          token: {
            endpoint: 'token',
            grantType: NbOAuth2GrantType.PASSWORD,
            class: NbAuthOAuth2Token,
          },
          refresh: {
            endpoint: 'refresh-token',
            grantType: NbOAuth2GrantType.REFRESH_TOKEN,
          },
        }),

Hope it helps

Choose a reason for hiding this comment

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

OK, I guess the API I am using is then not working according to the RFC.
Thanks for clearing that up!

@nnixaa nnixaa merged commit c8e8964 into akveo:master Aug 22, 2018
@nnixaa
Copy link
Collaborator

nnixaa commented Aug 22, 2018

@alain-charles congrats!

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

Successfully merging this pull request may close these issues.

None yet

3 participants