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 improvement : refresh-token are now saved if not repeated by the backend refresh endpoint #593

Merged
merged 60 commits into from
Aug 7, 2018
Merged

Feat/auth improvement : refresh-token are now saved if not repeated by the backend refresh endpoint #593

merged 60 commits into from
Aug 7, 2018

Conversation

alain-charles
Copy link
Contributor

@alain-charles alain-charles commented Jul 31, 2018

Feature/Auth : improvement on refreshable tokens

Short description of what this resolves:

At log on, some backends send Oauth2 token with a refresh-token value.
But some of them do no repeat the refresh token value when you then hit the refresh token endpoint.
So up to now, we were losing the refresh-token so that we were unable to send more than once a refresh token request

This PR corrects this problem: if necessary , it gets the existing refresh-token value in the current token and injects it in the refreshed token before storing it.

Hope it helps.

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.
alain-charles and others added 11 commits July 26, 2018 08:11
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
Bug
Refresh token value is now reinjected in the token before storage, in case the backend did not repeat it.
@alain-charles alain-charles changed the title Feat/auth automatic refresh token Feat/auth improvement : refresh-token are now kept if not repeated by the backent refres endpoint Jul 31, 2018
@alain-charles alain-charles changed the title Feat/auth improvement : refresh-token are now kept if not repeated by the backent refres endpoint Feat/auth improvement : refresh-token are now kept if not repeated by the backend refresh endpoint Jul 31, 2018
@alain-charles alain-charles changed the title Feat/auth improvement : refresh-token are now kept if not repeated by the backend refresh endpoint Feat/auth improvement : refresh-token are now saved if not repeated by the backend refresh endpoint Jul 31, 2018
@@ -16,11 +16,19 @@ export abstract class NbAuthToken {

export interface NbAuthRefreshableToken {
getRefreshToken(): string;
// Needed when refresh-token response does not repeat refresh_token value
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 so it is possible that after refreshing the token server may not return a new refresh token? Just looked through the RFC and this part looks vague.

In any case, I would propose to move this functionality into the refreshToken() method of the strategy. In this case, we have the current token and can extract the refresh part right there with no need for all additional checks.

What do you think?

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 think that you are a amazing code architect :)

reverted token, token-service and corresponding spec.ts files
@codecov
Copy link

codecov bot commented Jul 31, 2018

Codecov Report

Merging #593 into master will increase coverage by 0.04%.
The diff coverage is 100%.

@@            Coverage Diff             @@
##           master     #593      +/-   ##
==========================================
+ Coverage    72.8%   72.85%   +0.04%     
==========================================
  Files         153      153              
  Lines        4207     4214       +7     
  Branches      317      318       +1     
==========================================
+ Hits         3063     3070       +7     
  Misses       1087     1087              
  Partials       57       57
Impacted Files Coverage Δ
src/framework/auth/services/token/token.ts 95.23% <100%> (+0.09%) ⬆️
src/framework/auth/services/auth.service.ts 89.58% <100%> (ø) ⬆️
src/framework/auth/auth.options.ts 100% <100%> (ø) ⬆️
...ramework/auth/strategies/oauth2/oauth2-strategy.ts 87.4% <100%> (+0.51%) ⬆️
src/framework/auth/strategies/auth-strategy.ts 95.23% <100%> (ø) ⬆️

Copy link
Collaborator

@nnixaa nnixaa left a comment

Choose a reason for hiding this comment

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

@alain-charles one last change

@@ -199,13 +199,17 @@ export class NbOAuth2AuthStrategy extends NbAuthStrategy {
return this.http.post(url, this.buildRefreshRequestData(token), this.buildAuthHeader())
.pipe(
map((res) => {
const refreshedToken = <NbAuthOAuth2Token>this.createToken(res);
Copy link
Collaborator

Choose a reason for hiding this comment

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

let's just move this into a new method:

createRefreshedToken(res): NbAuthRefreshableToken {
...
}

and then call it almost as before:

return new NbAuthResult(
            true,
            res,
            this.getOption('redirect.success'),
            [],
            this.getOption('defaultMessages'),
            this.createRefreshedToken(res));

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@nnixaa
I think you mean

createRefreshedToken(res, existingToken): NbAuthOAuth2Token {
...
}

since we need the existing token for extracting the existing refresh_token

And NbAuthOAuth2Token instead of NbAuthRefreshableToken so that we return something assignable to NbAuthResult.token i.e 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 yes, of course, you are right.
But in the second part - return NbAuthOAuth2Token - is this always true? as by design we can assign any token to any strategy, so it is not necessary NbAuthOAuth2Token, but rather 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.

@nnixaa here is the best implementation i have found

  protected createRefreshedToken(res, existingToken: NbAuthRefreshableToken): NbAuthToken {
    const refreshedToken = this.createToken(res);
    if (isNbAuthRefreshableToken(refreshedToken)
        && !refreshedToken.getRefreshToken()
        && existingToken.getRefreshToken()) {
      refreshedToken.setRefreshToken(existingToken.getRefreshToken());
    }
    return refreshedToken;
  }

i think this is the one that is the most in the spirit of your architecture

authService : corrected the strategy.refreshToken() call : we were forgettong  to pass data as argument ?!
token : added isNbAuthRefreshableToken(token) method
@@ -376,6 +377,16 @@ export class NbOAuth2AuthStrategy extends NbAuthStrategy {
}, {}) : {};
}

protected createRefreshedToken(res, existingToken: NbAuthRefreshableToken): NbAuthToken {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I believe we can leave this check as:

if (!refreshedToken.getRefreshToken() && existingToken.getRefreshToken()) {

as we can only have the NbAuthRefreshableToken token here, which presumes that both required get and set method exist because this method could only be called from the refreshToken one, which cannot be called for a non-refreshable token.
In case when the developer forces a call of refreshToken method for a non-refreshble token it will be a typescript level error, which is completely fine in this case.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

!refreshedToken.getRefreshToken() does not compile as NbAuthToken (the return type) does not implement this method.
That is the reason why i added the isNbAuthRefreshableToken(refreshedToken) test

So what do you prefer :

  • should we return NbAuthOauth2Token ?
  • or just cast in the body of the method the refreshedToken to NbAuth0Auth2Token ?
  • or leave the code like in #10d0b31 commit ?

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 can we do this:

protected createRefreshedToken(res, existingToken: NbAuthToken & NbAuthRefreshableToken)

Sorry not able to check it myself.
If we can't, let's leave it as your current version.

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 sorry for the delay, wrote the comment last Thursday but forgot to submit.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@nnixaa with the intersection type you propose above, the problem remains on refreshedToken

const refreshedToken = this.createToken(res);

this.createToken(res) returns NbAuthToken that does not implement getRefreshToken().

Any other idea ?

Alain

Copy link
Collaborator

Choose a reason for hiding this comment

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

@nnixaa nnixaa merged commit dffbd59 into akveo:master Aug 7, 2018
@nnixaa
Copy link
Collaborator

nnixaa commented Aug 7, 2018

@alain-charles cool!

@alain-charles alain-charles deleted the feat/auth-AutomaticRefreshToken branch August 14, 2018 18:55
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

2 participants