Skip to content

alamin-mahamud/go-jwt

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

33 Commits
 
 
 
 
 
 
 
 

Repository files navigation

go-jwt

JWT Authentication Implementation in golang

Model

package models

type User struct {
	UUID     string `json:"uuid" form:"-"`
	Username string `json:"username" form:"username"`
	Password string `json:"password" form:"password"`
}

authentication

  • Backend
type JWTAuthenticationBackend struct {
	privateKey *rsa.PrivateKey
	publicKey *rsa.PublicKey
}

const (
	tokenDuration = 72
	expireOffset = 3600
)

using a package variable for the backendInstance

var authenticationBackendInstance *JWTAuthenticationBackend = nil

initializing authentication Backend

func InitJWTAuthenticationBackend() *JWTAuthenticationBackend{
	if authenticationBackendInstance == nil {
		authenticationBackendInstance = &JWTAuthenticationBackend{
			privateKey: getPrivateKey(),
			publicKey: getPublicKey(),
		}
	}
	
	return authenticationBackendInstance
}

get private key

func getPrivateKey() *rsa.PrivateKey{
	privateKeyFile, err := os.Open(settings.Get().PrivateKeyPath)
	defer privateKeyFile.Close()
	checkErrPanic(err)
	
	data := commonFileOperation(privateKeyFile)
	privateKeyImported, err := x509.ParsePKCS1PrivateKey(data.Bytes)
	checkErrPanic(err)
	
	return privateKeyImported
}

get public key

func getPublicKey *rsa.PublicKey{
	publicKeyFile, err := os.Open(settings.Get().PublicKeyPath)
    defer publicKeyFile.Close()
    checkErrPanic(err)

    data := commonFileOperation(publicKeyFile)
    publicKeyImported, err := x509.ParsePKIXPublicKey(data.Bytes)
    checkErrPanic(err)
    
    rsaPub, ok := publicKeyImported.(*rsa.PublicKey)
    if !ok {
    	panic("Could not convert to appropriate type.")
    }
    return rsaPub
}

common file operation

func commonFileOperation(f *os.File) *pem.Block {
	pemFileInfo, _ := f.Stat()
	var size int64 = pemFileInfo.Size()
    pemBytes = make([]byte, size)
    
    buffer := bufio.NewReader(f)
    _, err = buffer.Read(pemBytes)
    return data
}
func (backend *JWTAuthenticationBackend) GenerateToken(userUUID string)(string, error) {
	token := jwt.New(jwt.SigningMethodRS512)
	
	token.Claims = jwt.MapClaims{
		"exp": time.Now().Add(time.Hour * time.Duration(settings.Get().JWTExpirationDelta)),
		"iat": time.Now().Unix(),
		"sub": userUUID,
	}
	
	tokenString, err := token.SignedString(backend.privateKey)
	
	if err != nil {
		panic(err)
		return "", err
	}
}
func (backend *JWTAuthenticationBackend) Authenticate(user *model.User) bool {
	return user.Username == dbUser.Username &&
		bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(dbUser.Password)) == nil
}
func (backend *JWTAuthenticationBackend) Logout(tokenString string, token *jwt.Token) error {
	// Log out by doing necessary operations
	return nil
}
func (backend *JWTAuthenticationBackend) getTokenRemainingValidity(timestamp interface{}) int {
	if validity, ok := timestamp.(float64); ok {
		tm := time.Unix(int64(validity), 0)
		remainer := tm.Sub(time.Now())
		if remainer > 0 {
			return int(remainer.Seconds() + expireOffset)
		}
	}
	return expireOffset
}
func IsInBlackList(token string) bool {
	// 1. get user name or uuid
	// 2. find username or uuid in blackList Array
	// ok := findInBlackList(username)
	var ok bool = false
	
	if ok {
		return true
	}
	
	return false
}
  • Middleware
func RequireTokenAuthentication(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
    authBackend := InitJWTAuthenticationBackend()
    token, err := request.ParseFromRequest(req, request.OAuth2Extractor, func(token *jwt.Token)(interface{}, error){
    	if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok {
    		return nil, fmt.Errorf("Unexpected signing method: %v", token)
    	} else {
    	    return authBackend.PublicKey, nil	
    	}
    })
    
    if err == nil && token.Valid && !authBackend.IsInBlacklist(req.Header.Get("Authorization")) {
    		next(rw, req)
    	} else {
    		rw.WriteHeader(http.StatusUnauthorized)
    }
}

POST http://localhost:12345/authenticate

{
	"username": "alamin-mahamud",
  	"password": "simple-password"
}
// Response
{
	"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFsYW1pbi1tYWhhbXVkIn0.3pDO8lruVO2GAnABjknpMZK03XzsVktVBkNBmAbz-8I"
}

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Go 100.0%