mirror of
https://github.com/elyby/chrly.git
synced 2024-11-16 18:22:58 +05:30
Implemented jwt generation
This commit is contained in:
parent
d2485df64d
commit
ca4479252f
34
Gopkg.lock
generated
34
Gopkg.lock
generated
@ -1,6 +1,12 @@
|
||||
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
|
||||
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/SermoDigital/jose"
|
||||
packages = [".","crypto","jws","jwt"]
|
||||
revision = "f6df55f235c24f236d11dbcf665249a59ac2021f"
|
||||
version = "1.1"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/assembla/cony"
|
||||
packages = ["."]
|
||||
@ -55,6 +61,12 @@
|
||||
packages = [".","hcl/ast","hcl/parser","hcl/scanner","hcl/strconv","hcl/token","json/parser","json/scanner","json/token"]
|
||||
revision = "8f6b1344a92ff8877cf24a5de9177bf7d0a2a187"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/howeyc/gopass"
|
||||
packages = ["."]
|
||||
revision = "bf9dde6d0d2c004a008c27aaee91170c786f6db8"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/inconshreveable/mousetrap"
|
||||
packages = ["."]
|
||||
@ -73,6 +85,12 @@
|
||||
packages = ["cluster","pool","redis","util"]
|
||||
revision = "d234cfb904a91daafa4e1f92599a893b349cc0c2"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/mitchellh/go-homedir"
|
||||
packages = ["."]
|
||||
revision = "b8bc1bf767474819792c23f32d8286a45736f1c6"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/mitchellh/mapstructure"
|
||||
@ -109,6 +127,12 @@
|
||||
revision = "792786c7400a136282c1664665ae0a8db921c6c2"
|
||||
version = "v1.0.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/segmentio/go-prompt"
|
||||
packages = ["."]
|
||||
revision = "f0d19b6901ade831d5a3204edc0d6a7d6457fbb2"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/spf13/afero"
|
||||
@ -157,10 +181,16 @@
|
||||
revision = "69483b4bd14f5845b5a1e55bca19e954e827f1d0"
|
||||
version = "v1.1.4"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/crypto"
|
||||
packages = ["ssh/terminal"]
|
||||
revision = "0fcca4842a8d74bfddc2c96a073bd2a4d2a7a2e8"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/sys"
|
||||
packages = ["unix"]
|
||||
packages = ["unix","windows"]
|
||||
revision = "7ddbeae9ae08c6a06a59597f0c9edbc5ff2444ce"
|
||||
|
||||
[[projects]]
|
||||
@ -184,6 +214,6 @@
|
||||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
inputs-digest = "11938f85225b2839e4ed7cd4345bed8f44510b6eb50c003b89c8e14e0fd6b6e7"
|
||||
inputs-digest = "a12e681ec671ce8a93256cd754d4e70797476b2d2ce4379c3860df09c4b6a552"
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
||||
|
11
Gopkg.toml
11
Gopkg.toml
@ -23,6 +23,17 @@ ignored = ["elyby/minecraft-skinsystem"]
|
||||
name = "github.com/assembla/cony"
|
||||
version = "^0.3.2"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/SermoDigital/jose"
|
||||
version = "~1.1.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/mitchellh/go-homedir"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/segmentio/go-prompt"
|
||||
branch = "master"
|
||||
|
||||
# Testing dependencies
|
||||
|
||||
[[constraint]]
|
||||
|
124
auth/jwt.go
Normal file
124
auth/jwt.go
Normal file
@ -0,0 +1,124 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"io/ioutil"
|
||||
"math"
|
||||
"math/rand"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/SermoDigital/jose/crypto"
|
||||
"github.com/SermoDigital/jose/jws"
|
||||
"github.com/mitchellh/go-homedir"
|
||||
)
|
||||
|
||||
var hashAlg = crypto.SigningMethodHS256
|
||||
|
||||
const appHomeDirName = ".minecraft-skinsystem"
|
||||
const scopesClaim = "scopes"
|
||||
|
||||
type Scope string
|
||||
|
||||
var (
|
||||
SkinScope = Scope("skin")
|
||||
)
|
||||
|
||||
type JwtAuth struct {
|
||||
signingKey []byte
|
||||
}
|
||||
|
||||
func (t *JwtAuth) NewToken(scopes ...Scope) ([]byte, error) {
|
||||
key, err := t.getSigningKey()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
claims := jws.Claims{}
|
||||
claims.Set(scopesClaim, scopes)
|
||||
claims.SetIssuedAt(time.Now())
|
||||
encoder := jws.NewJWT(claims, hashAlg)
|
||||
token, err := encoder.Serialize(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return token, nil
|
||||
}
|
||||
|
||||
func (t *JwtAuth) GenerateSigningKey() error {
|
||||
if err := createAppHomeDir(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
key := generateRandomBytes(64)
|
||||
if err := ioutil.WriteFile(getKeyPath(), key, 0600); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *JwtAuth) getSigningKey() ([]byte, error) {
|
||||
if t.signingKey != nil {
|
||||
return t.signingKey, nil
|
||||
}
|
||||
|
||||
path := getKeyPath()
|
||||
if _, err := os.Stat(path); err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return nil, &SigningKeyNotAvailable{}
|
||||
}
|
||||
|
||||
return nil, err
|
||||
}
|
||||
|
||||
key, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return key, nil
|
||||
}
|
||||
|
||||
func createAppHomeDir() error {
|
||||
path := getAppHomeDirPath()
|
||||
if _, err := os.Stat(path); os.IsNotExist(err) {
|
||||
err := os.Mkdir(path, 0755) // rwx r-x r-x
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func getAppHomeDirPath() string {
|
||||
path, err := homedir.Expand("~/" + appHomeDirName)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return path
|
||||
}
|
||||
|
||||
func getKeyPath() string {
|
||||
return getAppHomeDirPath() + "/jwt-key"
|
||||
}
|
||||
|
||||
func generateRandomBytes(n int) []byte {
|
||||
randLen := int(math.Ceil(float64(n) / 1.37)) // base64 will increase length in 1.37 times
|
||||
randBytes := make([]byte, randLen)
|
||||
rand.Read(randBytes)
|
||||
resBytes := make([]byte, n)
|
||||
base64.URLEncoding.Encode(resBytes, randBytes)
|
||||
|
||||
return resBytes
|
||||
}
|
||||
|
||||
type SigningKeyNotAvailable struct {
|
||||
}
|
||||
|
||||
func (*SigningKeyNotAvailable) Error() string {
|
||||
return "Signing key not available"
|
||||
}
|
@ -41,6 +41,7 @@ func initConfig() {
|
||||
viper.AutomaticEnv()
|
||||
|
||||
if err := viper.ReadInConfig(); err == nil {
|
||||
// TODO: show only on verbose mode
|
||||
fmt.Println("Using config file:", viper.ConfigFileUsed())
|
||||
}
|
||||
}
|
||||
|
65
cmd/token.go
Normal file
65
cmd/token.go
Normal file
@ -0,0 +1,65 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"elyby/minecraft-skinsystem/auth"
|
||||
|
||||
"github.com/segmentio/go-prompt"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var tokenCmd = &cobra.Command{
|
||||
Use: "token",
|
||||
Short: "API tokens operations",
|
||||
}
|
||||
|
||||
var createCmd = &cobra.Command{
|
||||
Use: "create",
|
||||
Short: "Create the new token, that allows interacting with Ely.by Skinsystem API",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
jwtAuth := &auth.JwtAuth{}
|
||||
for {
|
||||
token, err := jwtAuth.NewToken(auth.SkinScope)
|
||||
if err != nil {
|
||||
if _, ok := err.(*auth.SigningKeyNotAvailable); !ok {
|
||||
log.Fatalf("Unable to create new token. The error is %v\n", err)
|
||||
}
|
||||
|
||||
log.Println("Signing key not available. Creating...")
|
||||
err := jwtAuth.GenerateSigningKey()
|
||||
if err != nil {
|
||||
log.Fatalf("Unable to generate new signing key. The error is %v\n", err)
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
fmt.Printf("%s\n", token)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
var resetCmd = &cobra.Command{
|
||||
Use: "reset",
|
||||
Short: "Regenerate the secret key, that invalidate all tokens",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if !prompt.Confirm("Do you really want to invalidate all exists tokens?") {
|
||||
fmt.Println("Aboart.")
|
||||
return
|
||||
}
|
||||
|
||||
jwtAuth := &auth.JwtAuth{}
|
||||
if err := jwtAuth.GenerateSigningKey(); err != nil {
|
||||
log.Fatalf("Unable to generate new signing key. The error is %v\n", err)
|
||||
}
|
||||
|
||||
fmt.Println("Token successfully regenerated.")
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
tokenCmd.AddCommand(createCmd, resetCmd)
|
||||
RootCmd.AddCommand(tokenCmd)
|
||||
}
|
Loading…
Reference in New Issue
Block a user