package services import ( "errors" "time" "github.com/golang-jwt/jwt" ) var ( users = map[string]string{ "henri": "henri123", } secret = []byte("mein-secret") ) type Session struct { Username string Expiry time.Time } type Credentials struct { Password string Username string } func (s Session) IsExpired() bool { return s.Expiry.Before(time.Now()) } func Signin(cred Credentials) (string, time.Time, error) { expectedPassword, ok := users[cred.Username] if !ok || expectedPassword != cred.Password { return "", time.Time{}, errors.New("wrong password") } expiresAt := time.Now().Add(2 * time.Hour) sessionToken, err := tokenFromSession(Session{ Username: cred.Username, Expiry: expiresAt, }) if err != nil { return "", time.Time{}, err } return sessionToken, expiresAt, nil } func GetSession(sessionToken string) (*Session, error) { return sessionFromToken(sessionToken) } func RemoveSession(sessionID string) { } func tokenFromSession(session Session) (string, error) { token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{ "username": session.Username, "exp": session.Expiry.Unix(), }) return token.SignedString(secret) } func sessionFromToken(tokenString string) (*Session, error) { sessionToken, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) { return secret, nil }) if err != nil { return nil, err } if !sessionToken.Valid { return nil, errors.New("invalid token") } if claims, ok := sessionToken.Claims.(jwt.MapClaims); ok { expiresAt := time.Unix(int64(claims["exp"].(float64)), 0) return &Session{ Username: claims["username"].(string), Expiry: expiresAt, }, nil } else { return nil, errors.New("cannot read claims") } }