diff --git a/Documentation/op-guide/configuration.md b/Documentation/op-guide/configuration.md index 7745bf490..d837d8b8a 100644 --- a/Documentation/op-guide/configuration.md +++ b/Documentation/op-guide/configuration.md @@ -361,8 +361,8 @@ Follow the instructions when using these flags. ## Auth flags ### --auth-token -+ Specify a token type and token specific options, especially for JWT. Its format is "type,var1=val1,var2=val2,...". Possible type is 'simple' or 'jwt'. Possible variables are 'sign-method' for specifying a sign method of jwt (its possible values are 'ES256', 'ES384', 'ES512', 'HS256', 'HS384', 'HS512', 'RS256', 'RS384', 'RS512', 'PS256', 'PS384', or 'PS512'), 'pub-key' for specifying a path to a public key for verifying jwt, and 'priv-key' for specifying a path to a private key for signing jwt. -+ Example option of JWT: '--auth-token jwt,pub-key=app.rsa.pub,priv-key=app.rsa,sign-method=RS512' ++ Specify a token type and token specific options, especially for JWT. Its format is "type,var1=val1,var2=val2,...". Possible type is 'simple' or 'jwt'. Possible variables are 'sign-method' for specifying a sign method of jwt (its possible values are 'ES256', 'ES384', 'ES512', 'HS256', 'HS384', 'HS512', 'RS256', 'RS384', 'RS512', 'PS256', 'PS384', or 'PS512'), 'pub-key' for specifying a path to a public key for verifying jwt, 'priv-key' for specifying a path to a private key for signing jwt, and 'ttl' for specifying TTL of jwt tokens. ++ Example option of JWT: '--auth-token jwt,pub-key=app.rsa.pub,priv-key=app.rsa,sign-method=RS512,ttl=10m' + default: "simple" ## Experimental flags diff --git a/auth/jwt.go b/auth/jwt.go index 99b2d6b5c..64535043c 100644 --- a/auth/jwt.go +++ b/auth/jwt.go @@ -18,6 +18,7 @@ import ( "context" "crypto/rsa" "io/ioutil" + "time" jwt "github.com/dgrijalva/jwt-go" ) @@ -26,6 +27,7 @@ type tokenJWT struct { signMethod string signKey *rsa.PrivateKey verifyKey *rsa.PublicKey + ttl time.Duration } func (t *tokenJWT) enable() {} @@ -70,6 +72,7 @@ func (t *tokenJWT) assign(ctx context.Context, username string, revision uint64) jwt.MapClaims{ "username": username, "revision": revision, + "exp": time.Now().Add(t.ttl).Unix(), }) token, err := tk.SignedString(t.signKey) @@ -83,7 +86,7 @@ func (t *tokenJWT) assign(ctx context.Context, username string, revision uint64) return token, err } -func prepareOpts(opts map[string]string) (jwtSignMethod, jwtPubKeyPath, jwtPrivKeyPath string, err error) { +func prepareOpts(opts map[string]string) (jwtSignMethod, jwtPubKeyPath, jwtPrivKeyPath string, ttl time.Duration, err error) { for k, v := range opts { switch k { case "sign-method": @@ -92,24 +95,36 @@ func prepareOpts(opts map[string]string) (jwtSignMethod, jwtPubKeyPath, jwtPrivK jwtPubKeyPath = v case "priv-key": jwtPrivKeyPath = v + case "ttl": + ttl, err = time.ParseDuration(v) + if err != nil { + plog.Errorf("failed to parse ttl option (%s)", err) + return "", "", "", 0, ErrInvalidAuthOpts + } default: plog.Errorf("unknown token specific option: %s", k) - return "", "", "", ErrInvalidAuthOpts + return "", "", "", 0, ErrInvalidAuthOpts } } if len(jwtSignMethod) == 0 { - return "", "", "", ErrInvalidAuthOpts + return "", "", "", 0, ErrInvalidAuthOpts } - return jwtSignMethod, jwtPubKeyPath, jwtPrivKeyPath, nil + return jwtSignMethod, jwtPubKeyPath, jwtPrivKeyPath, ttl, nil } func newTokenProviderJWT(opts map[string]string) (*tokenJWT, error) { - jwtSignMethod, jwtPubKeyPath, jwtPrivKeyPath, err := prepareOpts(opts) + jwtSignMethod, jwtPubKeyPath, jwtPrivKeyPath, ttl, err := prepareOpts(opts) if err != nil { return nil, ErrInvalidAuthOpts } - t := &tokenJWT{} + if ttl == 0 { + ttl = 5 * time.Minute + } + + t := &tokenJWT{ + ttl: ttl, + } t.signMethod = jwtSignMethod