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 : created NbAuthOauth2JWTToken class for handling Oauth2 tokens encapsulating jwt access_token #583

Merged
merged 50 commits into from
Jul 30, 2018

Conversation

alain-charles
Copy link
Contributor

What it does

The class NbAuthOauth2JWTToken has been created for handling oAuth2 backends whose access-token are jwt-token

To do

Implements some methods on the oAuth2 refreshtoken when it is in jwt format too ?
(may be useful in the future when refreshToken expired : useless in this case to send request to the resource backend, redirect to login)

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 20, 2018 19:28
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
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

missing semicolon after conflict resolution
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
* Returns access token payload
* @returns any
*/
getAccessTokenPayload(): any {
Copy link
Collaborator

Choose a reason for hiding this comment

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

so the getValue()) will return an encoded token and this method returns the decoded value, right?

so the complete token is encoded twice - the whole payload and the access token itself is also a jwt token, right?

Copy link
Contributor Author

@alain-charles alain-charles Jul 27, 2018

Choose a reason for hiding this comment

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

As for every token class, the getValue() method returns the string you have to put in the authorization header (Bearer). So yes, in this case, it returns the encoded payload of the access token

I do not know if we can say "encoded twice" since the Oauth2 token has a payload that is not 'encoded'. But yes, the complete token has got a payload with an access-token, that is a jwt token, i.e. the access-token has got a encoded payload with 'iss', 'iat', 'exp'.

I'm sorry, so sorry, but here i am not an IT head, so we have microsoft ADFS OAuth2 servers 😨 , and they put jwt access tokens in their Oauth2 token payload.

See here

Tokens used
These scenarios make use of three token types:

  • id_token: A JWT token used to represent the identity of the user. The 'aud' or audience claim of the id_token matches the client ID of the native or server application.
  • access_token: A JWT token used in Oauth and OpenID connect scenarios and intended to be consumed by the resource. The 'aud' or audience claim of this token must match the identifier of the resource or Web API.
  • refresh_token: This token is submitted in place of collecting user credentials to provide a single sign on experience. This token is both issued and consumed by AD FS, and is not readable by clients or resources.

Maybe here we will find other people who needs to athenticate against Microsoft Oauth2 ADFS servers...

Copy link
Collaborator

Choose a reason for hiding this comment

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

but probably this part should be in the app code already, not library? So that the getPayload will return a complete token payload and then you have to deal with the other parts of the token on your side?

Copy link
Collaborator

Choose a reason for hiding this comment

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

or otherwise we need to also have a getIdTokenPayload() method at least.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Well, just thought of it one more time, and probably this isn't that bad to put these methods inside of the JWTOAuth token, but then I propose the following:

getValue() - token string to put into request, access_token string in case of OAuth2
getRefreshToken() - refresh token string to put into request
getIdToken() - id token string to put into request
getAccessTokenPayload()
getIdTokenPayload()
getRefreshTokenPayload()

Copy link
Contributor Author

@alain-charles alain-charles Jul 27, 2018

Choose a reason for hiding this comment

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

i think you helped me in my reflexion. If i had to make the choice, i would send this PR to the recycle bin 🤣

The framework do not need to know what github's owner put in their damn Oauth2 tokens :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sorry it seems we had reflexion at the same time...
So do you want me do do that ?

getValue() - token string to put into request, access_token string in case of OAuth2
getRefreshToken() - refresh token string to put into request
getIdToken() - id token string to put into request
getAccessTokenPayload()
getIdTokenPayload()
getRefreshTokenPayload()

Copy link
Collaborator

Choose a reason for hiding this comment

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

Well, as we still have the default OAuth2 token implementation which is according to the spec, we can move forward with a complete implementation of OAuth2JWT token.

Copy link
Contributor Author

@alain-charles alain-charles Jul 27, 2018

Choose a reason for hiding this comment

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

@nnixaa
As far as i know, id_token JWT token is not part of the RFC 6749 oAuth2 spec.
But Section 8.4 of RFC 6749 allows extensions.

=> So id_token is defined by an extension of Oauth2 called OpenId Connect (implemented by Microsoft ADFS 2016, Azure, Google...)

If we want to introduce id_token, we have to introduce a new strategy (that probably extends NbOAuth2Strategy, let us call it NbOpenConnectIdStrategy), with the new response_type id_token, and any of the next combination :
id_token token
code id_token
code token
code id_token token
none

See the openid connect spec
See this excellent paper

We will then have to introduce a new token class for handling that, extending NbAuthOAuth2JWTToken, let's call it NbConnectIdToken.

It would be wonderful to succeed in doing that, but i think we have to make it in multiple PR (maybe a branch for working quiet ?). I would love to help writing that.

So maybe for the moment we can only merge the NbAuthOauth2JWT token as it is, fully compliant with rfc 6749, what do you think ?

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 yeah, that makes sense. Just a couple of related questions bellow.

@codecov
Copy link

codecov bot commented Jul 27, 2018

Codecov Report

Merging #583 into master will increase coverage by 0.14%.
The diff coverage is 100%.

@@            Coverage Diff             @@
##           master     #583      +/-   ##
==========================================
+ Coverage   68.82%   68.97%   +0.14%     
==========================================
  Files         120      120              
  Lines        3394     3410      +16     
  Branches      241      243       +2     
==========================================
+ Hits         2336     2352      +16     
  Misses       1014     1014              
  Partials       44       44
Impacted Files Coverage Δ
src/framework/auth/services/token/token.ts 95.14% <100%> (+0.89%) ⬆️

* Returns access token payload
* @returns any
*/
getAccessTokenPayload(): any {
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 yeah, that makes sense. Just a couple of related questions bellow.

protected prepareCreatedAt(date: Date) {
let decoded;
try {
decoded = this.getAccessTokenPayload();
Copy link
Collaborator

Choose a reason for hiding this comment

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

so in case when OAuth2 token is JWT, the iat fields is a part of JWT access token, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes exactly. Redundant with expires_in of the 'containing' token

* @returns Date
*/
getTokenExpDate(): Date {
if (this.getAccessTokenPayload() && this.getAccessTokenPayload().exp) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

and same here, exp is moved into the token payload?
if so, we need to make this getAccessTokenPayload call once and probably not cover it with a null check same way as for the other tokens

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes exp is present in the token.access-token payload
OK i'll see that

date = super.prepareCreatedAt(date);
let decoded = null;
try { // needed as getPayload() throws error and we want the token to be created in any case
let decoded
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 aed2099 into akveo:master Jul 30, 2018
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