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

JWT: Upgrade from v3 to v5 #193

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
Open

Conversation

freddierice
Copy link

The current jwt code has been deprecated in the upstream This PR aims to upgrade the library to v5.

This will make upgrading for security vulnerabilities / bugs easier in the future.

Big Changes

  1. StandardClaims has been deprecated -- RegisteredClaims is the new struct to use.
  2. The library prefers audience as an array (but allows us to turn it off with the global variable MarshalSingleStringAsArray)

@freddierice
Copy link
Author

I resolved a go mod conflict, but then forgot to run go mod tidy -- should work now.

@freddierice
Copy link
Author

Sorry about that. I got it to pass the build and test portion in my forked repo. Now I'm stuck at a linting error that says I can't use init() functions. As a general practice, I think that makes sense, but I think this is a reasonable usecase. The new jwt package has a global variable that needs to be set to true before any of the auth package code runs. How would you like me to approach that?

@umputun
Copy link
Member

umputun commented Jan 17, 2024

How would you like me to approach that?

can this be set in NewService (auth.go)? Or this be too late?

@freddierice
Copy link
Author

The unit tests in the token package would stop working. I think the init function is the right approach in this case, because we are configuring the jwt package before we run any code from the token package.

@umputun
Copy link
Member

umputun commented Jan 17, 2024

Well, the token's Service has token.NewService constructor, which to me seems to be the good place to put this jwt init thing. From what i can see all the tests for token start with NewService

@freddierice
Copy link
Author

Moved the variable. The linter didn't seem to run right on my fork, but at least the tests did.

@freddierice
Copy link
Author

@coveralls
Copy link

Pull Request Test Coverage Report for Build 7563891591

  • 0 of 0 changed or added relevant lines in 0 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage decreased (-0.07%) to 82.676%

Totals Coverage Status
Change from base Build 7552291388: -0.07%
Covered Lines: 2577
Relevant Lines: 3117

💛 - Coveralls

@@ -22,7 +22,7 @@ import (
log "github.com/go-pkgz/lgr"
"github.com/go-pkgz/rest"
"github.com/go-pkgz/rest/logger"
"github.com/golang-jwt/jwt"
oldjwt "github.com/golang-jwt/jwt"
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is there any reason to keep old version of JWT for an example instead of updating it here as well?

Copy link
Author

Choose a reason for hiding this comment

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

The external library wants to consume that specific function. Once the external library also upgrades, it will make sense to bump.

Copy link
Member

Choose a reason for hiding this comment

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

Can you please clarify this part? What exactly "the external library" do you mean?

Copy link
Author

Choose a reason for hiding this comment

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

oldjwt is used in only one place -- as input to github.com/go-oauth2/oauth2/v4/manage. Sure, you could rewrite it, but that's not what the manage package expects.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I've tried, and I think it doesn't make sense. The dependency will move from direct to indirect, and example code will become more complicated. See the link for the results.

@paskal
Copy link
Collaborator

paskal commented Jan 18, 2024

Just so you know these are the changes which have to be implemented in Remark42 after updating to the go-pkgz/auth version from that PR. The changes are significant enough to release v2.

I propose to mark the current master as the last release of v1 and then bump the major version of this library after the merge. I thought of updating to jwt v4 many times before, but the necessity to break backwards compatibility stopped me.

@umputun
Copy link
Member

umputun commented Jan 18, 2024

The part that worries me is that you had to change JWT for tests. I thought the reason was aud related, but it seems to have a string aud, not an array. So, I'm puzzled why it was needed

Before:

image

after:

image

I don't see any reason why this would be the case, and this is something I want to understand. As long as both versions produce the same jwt the change would be back compatible, but if for some reason it is not - this is kind of big deal as we may invalidate all the "sessions" and should carefully test the migration path, i.e. what will happen if the new version will get "old" token

But as I said above - I don't really get why token is different

@freddierice
Copy link
Author

The order of "aud" and "iss" are different because the new version of the library changed the types of each of the members. "aud" is now a union type of string and []string. While the jwt string itself is different, it will get decoded the same.

@freddierice
Copy link
Author

freddierice commented Jan 18, 2024

@umputun
Copy link
Member

umputun commented Jan 18, 2024

The order of "aud" and "iss" are different because the new version of the library changed the types of each of the members. "aud" is now a union type of string and []string. While the jwt string itself is different, it will get decoded the same.

Will the new version properly verify the old message? It should be because the signature matches the content. But what will happen next? I mean, will the old message be correctly decoded/unmarshaled, or will the order of fields prevent it from happening?

Having a test consuming the old token should help to clarify this scenario

@freddierice
Copy link
Author

Field ordering doesn't matter for golang's json.Unmarshal functions. Unfortunately I can't put any more time into this, but feel free to take/leave whichever parts you want.

@umputun
Copy link
Member

umputun commented Jan 18, 2024

@freddierice Thank you very much, we will deal with this.

@paskal assuming old tokens will continue to work, what is the part breaking back compatibility? I don't see anything on the exposed level that will require any change on the consumer side. I have not checked it in detail, but on the surface, it seems to be back-compatible.

@paskal
Copy link
Collaborator

paskal commented Mar 22, 2024

Here are the changes due to migration to v5. I prefer to cut the current master as v1 of this library and release version v2 with JWTv5 + a minor breaking change of setting the type explicitly here in RefreshCache as it has interface{} in its signature purely by mistake.

As a user of this library JWTv5 changes seem inconvenient enough to cut a new release for me.

@paskal
Copy link
Collaborator

paskal commented Apr 4, 2024

I've prepared #200, and once it's merged, I'll ask you to change the PR to target the v2 directory.

I want to clarify one interface used for cache to specify types explicitly, which is a breaking change strictly speaking. I consider changes in this PR breaking as well, as they require some users to change their code after the update.

@paskal
Copy link
Collaborator

paskal commented Apr 10, 2024

FYI, I think you can copy all changed files to v2, fix imports, re-run go get to get v5 of JWT, and it will be enough to get PR ready for v2.

@paskal
Copy link
Collaborator

paskal commented Apr 10, 2024

The changes in branch https://github.com/go-pkgz/auth/tree/paskal/v2_jwt5 have been moved to the v2 directory. Feel free to copy them to this PR.

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

4 participants