Comments (7)
Yeah, that's definitely not the best way to do this.
I think there's some confusion here. When you're saying "claims", I guess you're referring to JWT which this library doesn't use by default. It does use and generate tokens, but not JWT. That's why you can't add 'claims' to the default token model, because it's not a JWT and there's no such thing as 'claims',
just a replaceable AccessGenerate struct to generate the access_token.
So, how is the access token generated?
If you take a look at the code in the manager.go:GenerateAccessToken, the access_token is generated here
It instantiates the default AccessGenerate: generates/access.go In that file, the Token() method generates the access_token itself.
After generating the access_token, the token info is stored in the token store to (I believe, correct me if I'm wrong @LyricTian) later retrieve the token info from the store (in memory or persistent), rather than decoding the access_token and to store the token so you can e.g. invalidate it —and that kind of stuff— with the tokenStore (you can use the tokenStore methods for that).
How to create a custom access token?
Good news are that you CAN change the way the access token is generated, as the README states: you CAN use JWT to generate access tokens.
How? Easy. Just use a custom AccessGenerate struct like the one in generates/access.go . The library itself includes here: generates/jwt_access.go the JWTAccessGenerate you need to create custom access_token with JWT.
Change that file as you want with the claims you want:
func (a *JWTAccessGenerate) Token(data *oauth2.GenerateBasic, isGenRefresh bool) (access, refresh string, err error) {
claims := &JWTAccessClaims{
ClientID: data.Client.GetID(),
UserID: data.UserID,
ExpiredAt: data.TokenInfo.GetAccessCreateAt().Add(data.TokenInfo.GetAccessExpiresIn()).Unix(),
}
token := jwt.NewWithClaims(a.SignedMethod, claims)
var key interface{}
and then change the AccessGenerate used by default with manager.MapAccessGenerate():
import "gopkg.in/oauth2.v3/generates"
import "github.com/dgrijalva/jwt-go"
// ...
manager.MapAccessGenerate(generates.NewJWTAccessGenerate([]byte("00000000"), jwt.SigningMethodHS512))
If you want to parse it and retrieve the claims, use the JWT library (as in the README.md):
import "github.com/dgrijalva/jwt-go"
// Verify jwt access token
token, err := jwt.ParseWithClaims(access, &generates.JWTAccessClaims{}, func(t *jwt.Token) (interface{}, error) {
if _, ok := t.Method.(*jwt.SigningMethodHMAC); !ok {
return nil, fmt.Errorf("parse error")
}
return []byte("00000000"), nil
})
if err != nil {
panic(err)
}
claims, ok := token.Claims.(*generates.JWTAccessClaims)
if !ok || !token.Valid {
panic("invalid token")
}
In my opinion, I would strongly recommend using a custom JWTAccessGenerate to generate your access_token, even if you don't need custom claims.
Just because then you could generate a JWT access_token with asymmetric encryption (like RSA), and you'd have a public and a private key in your auth server and only the public key in the Resource server. This way you can verify and decode tokens from the resource server without additional round trips to the auth server.
To conclude, I would want to thank you @LyricTian for this great library. It's well-coded and it's easy to customize, but as a suggestion I would pick someone who speaks native english (I don't) or open an issue with a 'help needed' label to look for someone, and get him to write up some documentation explaining this sort of things (eg. How is the access token generated, how to change the AccessGenerate, digging into the custom handlers —which I would rename to lifecycle hooks because at first I thought that by 'handlers' you were referring to something related with HTTP because 'handler' is like a convention in golang, also: isGenerateRefresh to allowRefresh.. but that would mean breaking changes so...—, etc.)
Anyway, I hope this helps anyone to add custom JWT claims.
from oauth2.
I would like to thank @pmrt for his answer 👏.
Also I would like to ask why not use JWT standard claims. For example this mapping:
user_id
: "sub"
(https://tools.ietf.org/html/rfc7519#section-4.1.2)
expire_at
: "exp"
(https://tools.ietf.org/html/rfc7519#section-4.1.4)
client_id
: "aud"
(https://tools.ietf.org/html/rfc7519#section-4.1.3)
These are also specified here: https://github.com/dgrijalva/jwt-go/blob/06ea1031745cb8b3dab3f6a236daf2b0aa468b7e/claims.go#L18
I've created draft PR if I'm not clear :) ... #102
from oauth2.
You are right, at the time of writing my comment I was under impression that aud should be used differently than its actual purpose.
from oauth2.
UserID is a string type, you can encode the data you need into a string using JSON encoding.
from oauth2.
you means to say to use userID for all the claims
from oauth2.
An example of adding public and/or private custom claims would be nice, as this is not obvious to me.
from oauth2.
I would like to thank @pmrt for his answer 👏.
Also I would like to ask why not use JWT standard claims. For example this mapping:
user_id
:"sub"
(https://tools.ietf.org/html/rfc7519#section-4.1.2)
expire_at
:"exp"
(https://tools.ietf.org/html/rfc7519#section-4.1.4)
client_id
:"aud"
(https://tools.ietf.org/html/rfc7519#section-4.1.3)These are also specified here: https://github.com/dgrijalva/jwt-go/blob/06ea1031745cb8b3dab3f6a236daf2b0aa468b7e/claims.go#L18
I've created draft PR if I'm not clear :) ... #102
Thanks for the PR. 👍
One question about the standard claims:
AFAIK, "aud"
in OAuth2 refers to the Resource Server that accepts this token, normally it would be the url of the resource. see discussion.
"sub"
would be relevant to the client_id
or user_id
depending on which OAuth2 Grant Type is involved (whether it is user-driven or machine-to-machine)
from oauth2.
Related Issues (20)
- server support for device code auth flow
- [Question] ed25519 sign method support ?
- use base64.RawURLEncoding instead of trimming the padding
- [bug]failed to refresh token
- Does this library support authentication via google and facebook? HOT 3
- When obtaining the token through auth2 concurrently, only the scope value is different, but the returned token is the same HOT 1
- Redirect URI is not compared to configured value HOT 2
- 我在go-zero中集成go-oauth2后,如何跨服务验证token HOT 1
- Is it possible to put the client id and client secret in headers instead of query params?
- how to handle concurrency/unique sessions
- Feature Request: use a local time.Now implementation through module to support testing
- GetRedirectURI return sso code url err HOT 2
- There is no method provided to clean up the specified clientid in the clientstore.
- configuring multiple domains for redirect_uri
- AllowedCodeChallengeMethods is forced to include plain.
- Why must set UserAuthorizationHandler? HOT 1
- Retrieve the clientID using the token?
- Missing refresh_token in response for client_credentials HOT 1
- Example doesn't work - access_denied HOT 2
- Validating redirect_uri via ValidateURIHandler is a bit weird
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from oauth2.