iris/_examples/mvc/websocket-auth/user_provider.go
Gerasimos (Makis) Maropoulos e7f5efa058
minor
2022-05-24 01:44:36 +03:00

102 lines
2.3 KiB
Go

//go:build go1.18
// +build go1.18
package main
import (
"context"
"fmt"
"sync"
"time"
"github.com/kataras/iris/v12/auth"
)
type Provider struct {
dataset []User
invalidated map[string]struct{} // key = token. Entry is blocked.
invalidatedAll map[string]int64 // key = user id, value = timestamp. Issued before is consider invalid.
mu sync.RWMutex
}
func NewProvider() *Provider {
return &Provider{
dataset: []User{
{
ID: "id-1",
Email: "kataras2006@hotmail.com",
Role: Owner,
},
{
ID: "id-2",
Email: "example@example.com",
Role: Member,
},
},
invalidated: make(map[string]struct{}),
invalidatedAll: make(map[string]int64),
}
}
func (p *Provider) Signin(ctx context.Context, username, password string) (User, error) { // fired on SigninHandler.
// your database...
for _, user := range p.dataset {
if user.Email == username {
return user, nil
}
}
return User{}, fmt.Errorf("user not found")
}
func (p *Provider) ValidateToken(ctx context.Context, standardClaims auth.StandardClaims, u User) error { // fired on VerifyHandler.
// your database and checks of blocked tokens...
// check for specific token ids.
p.mu.RLock()
_, tokenBlocked := p.invalidated[standardClaims.ID]
if !tokenBlocked {
// this will disallow refresh tokens with issuer as the blocked access token as well.
if standardClaims.Issuer != "" {
_, tokenBlocked = p.invalidated[standardClaims.Issuer]
}
}
p.mu.RUnlock()
if tokenBlocked {
return fmt.Errorf("token was invalidated")
}
//
// check all tokens issuet before the "InvalidateToken" method was fired for this user.
p.mu.RLock()
ts, oldUserBlocked := p.invalidatedAll[u.ID]
p.mu.RUnlock()
if oldUserBlocked && standardClaims.IssuedAt <= ts {
return fmt.Errorf("token was invalidated")
}
//
return nil // else valid.
}
func (p *Provider) InvalidateToken(ctx context.Context, standardClaims auth.StandardClaims, u User) error { // fired on SignoutHandler.
// invalidate this specific token.
p.mu.Lock()
p.invalidated[standardClaims.ID] = struct{}{}
p.mu.Unlock()
return nil
}
func (p *Provider) InvalidateTokens(ctx context.Context, u User) error { // fired on SignoutAllHandler.
// invalidate all previous tokens came from "u".
p.mu.Lock()
p.invalidatedAll[u.ID] = time.Now().Unix()
p.mu.Unlock()
return nil
}