goOauth2

package module
v0.0.0-...-52b2201 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 29, 2020 License: MIT Imports: 21 Imported by: 0

README

Golang Oauth2 with jwt OAuth 2.0

Build Go Report Card GoDoc

This project is modified version of go-oauth2/oauth2. Since that didn't meet my requirement so I modified the code so I can implement oauth2 alongside with JWT.
This package uses EncryptOAEP which encrypts the given data with RSA-OAEP to encrypt token data. Two separate file private.pem and public.pem file will be created on your root folder which includes respective private and public RSA keys which is used for encryption.
This package only handles Resource Owner Password Credentials type.
Official docs: Here

Install

$ go get -u -v github.com/roshanr83/go-oauth2

Usage

package main

import (
	_ "github.com/go-sql-driver/mysql"
	"github.com/google/uuid"
	"github.com/roshanr83/go-oauth2"
	"gopkg.in/go-oauth2/mysql.v3"
	"time"
)

func main() {
	//register store
	store := oauth.NewDefaultStore(
		oauth.NewConfig("root:root@tcp(127.0.0.1:8889)/goauth?charset=utf8&parseTime=True&loc=Local"),
	)
	defer store.Close()



	/* to create client
	 where 1 is user ID Which will return Oauth Clients
	 struct which include client id and secret whic is
	 later used to validate client credentials */
	store.CreateClient(userId int64)



	/* create access token alongside refresh token
	Since it will not include user authentication
	because it can be  different for everyone you will
	have to authenticate user and pass user id to Token struct.
	 Here you will authenticate user and get userID
	 you will have to provide all the field given below.
	 ClientID must be  valid uuid. AccessExpiresIn is required
	 to mark expiration time. In response you will get TokenResponse
	 including accesstoken and refeshtoken. */
	accessToken := &oauth.Token{
		ClientID:        uuid.MustParse("17d5a915-c403-487e-b41f-92fd1074bd30"),
		ClientSecret:    "UnCMSiJqxFg1O7cqL0MM",
		UserID:          userID,
		Scope:           "*",
		AccessCreateAt:  time.Now(),
		AccessExpiresIn: time.Second * 15,
		RefreshCreateAt: time.Now(),
	}
	resp, err := store.Create(accessToken TokenInfo)



	/*To check valid accessToken, you should
	pass accessToken and it will check if it is valid accesstoken
	including if it is valid and non revoked. If it is valid
	in response it will return AccessTokens data correspond to that token */
	resp, err := store.GetByAccess(accessToken string)



	/* To check valid refreshToken, you should pass
	refreshToken and it will check if it is valid
	refreshToken including if it is valid and non revoked
	and if it;s related accessToken is already revoked or
	not. If it is valid in response it will return AccessTokens
	data correspond to that token*/
	/* Note that refresh token after using one time
	will be revoked and cannot be used again */
	resp, err := store.GetByRefresh(refreshToken string)



	/*You can manually revoke access token by passing
	userId which you can get from valid token info */
	store.RevokeByAccessTokens(userId int64)



	/*You can manually revoke refresh token by passing
	accessTokenId which you can get from valid token info */
	store.RevokeRefreshToken(accessTokenId string)



	/* you can also clear all token related to
	user by passing TokenInfo from valid token */
	store.ClearByAccessToken(userId int64)
	
}


Running the tests

Database config is used as "root:root@tcp(127.0.0.1:3306)/goauth?charset=utf8&parseTime=True&loc=Local" in const.go file, You may have to change that configuration according to your system config for successful test.

$ go test

Contributing

Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.

Please make sure to update tests as appropriate.

Acknowledgments

  1. https://github.com/go-oauth2/oauth2

MIT License

Copyright (c) 2019

Documentation

Index

Constants

View Source
const (
	PublicPem           = "public.pem"
	PrivatePem          = "private.pem"
	AccessTokenTable    = "oauth_access_tokens"
	RefreshTokenTable   = "oauth_refresh_tokens"
	ClientTable         = "oauth_clients"
	BitSize             = 2048
	RefreshTokenRevoked = "refresh token already been revoked"
	AccessTokenRevoked  = "access token has already been revoked"
	AccessTokenExpired  = "access token has already been expired"
	InvalidRefreshToken = "invalid refresh token"
	InvalidAccessToken  = "invalid access token"
	InvalidClient       = "invalid client"
	EmptyUserID         = "user id cannot be empty"
	Label               = "OAEP Encrypted"
	PublicKey           = "PUBLIC KEY"
	PrivateKey          = "PRIVATE KEY"
)

constants

Variables

View Source
var RandomKeyCharacters = []byte("abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ")

RandomKeyCharacters is random key characters to choose from

Functions

func BytesToPrivateKey

func BytesToPrivateKey(priv []byte) *rsa.PrivateKey

BytesToPrivateKey converts given bytes to *rsa.PrivateKey

func BytesToPublicKey

func BytesToPublicKey(pub []byte) *rsa.PublicKey

BytesToPublicKey converts given bytes to *rsa.PublicKey

func DecryptWithPrivateKey

func DecryptWithPrivateKey(cipherText string, priv *rsa.PrivateKey) (string, error)

DecryptWithPrivateKey decrypts given []byte, with private key

func EncryptWithPublicKey

func EncryptWithPublicKey(msg []byte, pub *rsa.PublicKey) (string, error)

EncryptWithPublicKey encrypts given []byte, with public key

func GenerateKeyPair

func GenerateKeyPair(bits int) (*rsa.PrivateKey, *rsa.PublicKey)

GenerateKeyPair generates a new key pair

func RandomKey

func RandomKey(length int) string

RandomKey generates random characters from RandomKeyCharacters

func SavePEMKey

func SavePEMKey(fileName string, key *rsa.PrivateKey)

SavePEMKey saves generated *rsa.PrivateKey to file

func SavePublicPEMKey

func SavePublicPEMKey(fileName string, pubkey *rsa.PublicKey)

SavePublicPEMKey saves generated *rsa.PublicKey to file

Types

type AccessTokenPayload

type AccessTokenPayload struct {
	UserId    int64     `db:"user_id"`
	ClientId  uuid.UUID `db:"client_id"`
	ExpiredAt int64     `db:"expired_at"`
}

AccessTokenPayload is data that will be encrypted by RSA encryption

type AccessTokens

type AccessTokens struct {
	Model
	AccessTokenPayload
	Name    string `db:"name"`
	Revoked bool   `db:"revoked"`
}

AccessTokens is model for Oauth Access Token

type Clients

type Clients struct {
	Model
	UserId   int64  `db:"user_id"`
	Name     string `db:"name"`
	Secret   string `db:"secret"`
	Revoked  bool   `db:"revoked"`
	Redirect string `db:"redirect"`
}

Clients is model for oauth clients

type Config

type Config struct {
	DSN          string
	MaxLifetime  time.Duration
	MaxOpenConns int
	MaxIdleConns int
}

Config mysql configuration

func NewConfig

func NewConfig(dsn string) *Config

NewConfig create mysql configuration instance, dsn mysql database credential

type Model

type Model struct {
	ID        uuid.UUID `db:"id,primarykey"`
	CreatedAt time.Time `db:"created_at"`
	UpdatedAt time.Time `db:"updated_at"`
}

Model is default model

type RefreshTokenPayload

type RefreshTokenPayload struct {
	AccessTokenId uuid.UUID `db:"access_token_id"`
}

RefreshTokenPayload is model for oauth refresh token

type RefreshTokens

type RefreshTokens struct {
	Model
	RefreshTokenPayload
	Revoked bool `db:"revoked"`
}

RefreshTokens is model for oauth refresh token

type Store

type Store struct {
	// contains filtered or unexported fields
}

Store mysql token store model

func NewDefaultStore

func NewDefaultStore(config *Config) *Store

NewDefaultStore create mysql store instance, config mysql configuration,

func NewStore

func NewStore(config *Config, gcInterval int) *Store

NewStore create mysql store instance, config mysql configuration, GC time interval (in seconds, default 600)

func NewStoreWithDB

func NewStoreWithDB(db *sql.DB, gcInterval int) *Store

NewStoreWithDB create mysql store instance, db sql.DB, GC time interval (in seconds, default 600)

func (*Store) ClearByAccessToken

func (s *Store) ClearByAccessToken(userId int64) error

ClearByAccessToken clears all token related to user, userId id of user whose access token needs to be cleared

func (*Store) Close

func (s *Store) Close()

Close close the store

func (*Store) Create

func (s *Store) Create(info TokenInfo) (TokenResponse, error)

Create create and store the new token information

func (*Store) CreateClient

func (s *Store) CreateClient(userId int64) (Clients, error)

CreateClient creates new client, userId user's id who created the client

func (*Store) GetByAccess

func (s *Store) GetByAccess(access string) (*AccessTokens, error)

GetByAccess use the access token for token information data, access Access token string

func (*Store) GetByRefresh

func (s *Store) GetByRefresh(refresh string) (*AccessTokens, error)

GetByRefresh use the refresh token for token information data, refresh Refresh token string

func (*Store) RevokeByAccessTokens

func (s *Store) RevokeByAccessTokens(userId int64) error

RevokeByAccessTokens revokes token from accessToken

func (*Store) RevokeRefreshToken

func (s *Store) RevokeRefreshToken(accessTokenId string) error

RevokeRefreshToken revokes token from RefreshToken,

type Token

type Token struct {
	ClientID         uuid.UUID     `bson:"ClientID"`
	ClientSecret     string        `bson:"ClientSecret"`
	UserID           int64         `bson:"UserID"`
	RedirectURI      string        `bson:"RedirectURI"`
	Scope            string        `bson:"Scope"`
	AccessCreateAt   time.Time     `bson:"AccessCreateAt"`
	AccessExpiresIn  time.Duration `bson:"AccessExpiresIn"`
	RefreshCreateAt  time.Time     `bson:"RefreshCreateAt"`
	RefreshExpiresIn time.Duration `bson:"RefreshExpiresIn"`
}

Token struct which hold token details

func NewToken

func NewToken() *Token

NewToken create to token model instance

func (*Token) GetAccessCreateAt

func (t *Token) GetAccessCreateAt() time.Time

GetAccessCreateAt create Time

func (*Token) GetAccessExpiresIn

func (t *Token) GetAccessExpiresIn() time.Duration

GetAccessExpiresIn the lifetime in seconds of the access token

func (*Token) GetClientID

func (t *Token) GetClientID() uuid.UUID

GetClientID the client id

func (*Token) GetClientSecret

func (t *Token) GetClientSecret() string

GetClientSecret the client id

func (*Token) GetRedirectURI

func (t *Token) GetRedirectURI() string

GetRedirectURI redirect URI

func (*Token) GetRefreshCreateAt

func (t *Token) GetRefreshCreateAt() time.Time

GetRefreshCreateAt create Time

func (*Token) GetRefreshExpiresIn

func (t *Token) GetRefreshExpiresIn() time.Duration

GetRefreshExpiresIn the lifetime in seconds of the refresh token

func (*Token) GetScope

func (t *Token) GetScope() string

GetScope get scope of authorization

func (*Token) GetUserID

func (t *Token) GetUserID() int64

GetUserID the user id

func (*Token) New

func (t *Token) New() TokenInfo

New create to token model instance

func (*Token) SetAccessCreateAt

func (t *Token) SetAccessCreateAt(createAt time.Time)

SetAccessCreateAt create Time

func (*Token) SetAccessExpiresIn

func (t *Token) SetAccessExpiresIn(exp time.Duration)

SetAccessExpiresIn the lifetime in seconds of the access token

func (*Token) SetClientID

func (t *Token) SetClientID(clientID uuid.UUID)

SetClientID the client id

func (*Token) SetClientSecret

func (t *Token) SetClientSecret() string

SetClientSecret the client id

func (*Token) SetRedirectURI

func (t *Token) SetRedirectURI(redirectURI string)

SetRedirectURI redirect URI

func (*Token) SetRefreshCreateAt

func (t *Token) SetRefreshCreateAt(createAt time.Time)

SetRefreshCreateAt create Time

func (*Token) SetRefreshExpiresIn

func (t *Token) SetRefreshExpiresIn(exp time.Duration)

SetRefreshExpiresIn the lifetime in seconds of the refresh token

func (*Token) SetScope

func (t *Token) SetScope(scope string)

SetScope get scope of authorization

func (*Token) SetUserID

func (t *Token) SetUserID(userID int64)

SetUserID the user id

type TokenInfo

type TokenInfo interface {
	New() TokenInfo

	GetClientID() uuid.UUID
	SetClientID(uuid.UUID)
	GetClientSecret() string
	SetClientSecret() string
	GetUserID() int64
	SetUserID(int64)
	GetRedirectURI() string
	SetRedirectURI(string)
	GetScope() string
	SetScope(string)

	GetAccessCreateAt() time.Time
	SetAccessCreateAt(time.Time)
	GetAccessExpiresIn() time.Duration
	SetAccessExpiresIn(time.Duration)

	GetRefreshCreateAt() time.Time
	SetRefreshCreateAt(time.Time)
	GetRefreshExpiresIn() time.Duration
	SetRefreshExpiresIn(time.Duration)
}

TokenInfo the token information model interface

type TokenResponse

type TokenResponse struct {
	AccessToken  string `json:"access_token"`
	RefreshToken string `json:"refresh_token"`
	ExpiredAt    int64  `json:"expired_at"`
}

TokenResponse model after creating access token and refresh token

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL