Merge branch 'auth' into dev
All checks were successful
Build and Deploy Go App / build (push) Successful in 5m58s
Build and Deploy Go App / deploy (push) Successful in 40s

This commit is contained in:
nihonium 2025-12-06 04:51:24 +03:00
commit 003a477f9e
Signed by: nihonium
GPG key ID: 0251623741027CFC
7 changed files with 236 additions and 95 deletions

View file

@ -47,10 +47,28 @@ func CheckPassword(password, hash string) (bool, error) {
return argon2id.ComparePasswordAndHash(password, hash)
}
func (s Server) generateImpersonationToken(userID string, impersonated_by string) (accessToken string, err error) {
accessClaims := jwt.MapClaims{
"user_id": userID,
"exp": time.Now().Add(15 * time.Minute).Unix(),
"imp_id": impersonated_by,
}
at := jwt.NewWithClaims(jwt.SigningMethodHS256, accessClaims)
accessToken, err = at.SignedString([]byte(s.JwtPrivateKey))
if err != nil {
return "", err
}
return accessToken, nil
}
func (s Server) generateTokens(userID string) (accessToken string, refreshToken string, csrfToken string, err error) {
accessClaims := jwt.MapClaims{
"user_id": userID,
"exp": time.Now().Add(15 * time.Minute).Unix(),
//TODO: add created_at
}
at := jwt.NewWithClaims(jwt.SigningMethodHS256, accessClaims)
accessToken, err = at.SignedString([]byte(s.JwtPrivateKey))
@ -119,10 +137,7 @@ func (s Server) PostSignIn(ctx context.Context, req auth.PostSignInRequestObject
// TODO: return 500
}
if !ok {
err_msg := "invalid credentials"
return auth.PostSignIn401JSONResponse{
Error: &err_msg,
}, nil
return auth.PostSignIn401Response{}, nil
}
accessToken, refreshToken, csrfToken, err := s.generateTokens(req.Body.Nickname)
@ -144,6 +159,40 @@ func (s Server) PostSignIn(ctx context.Context, req auth.PostSignInRequestObject
return result, nil
}
func (s Server) GetImpersonationToken(ctx context.Context, req auth.GetImpersonationTokenRequestObject) (auth.GetImpersonationTokenResponseObject, error) {
ginCtx, ok := ctx.Value(gin.ContextKey).(*gin.Context)
if !ok {
log.Print("failed to get gin context")
// TODO: change to 500
return auth.GetImpersonationToken200JSONResponse{}, fmt.Errorf("failed to get gin.Context from context.Context")
}
token, err := ExtractBearerToken(ginCtx.Request.Header.Get("Authorization"))
if err != nil {
// TODO: return 500
log.Errorf("failed to extract bearer token: %v", err)
return auth.GetImpersonationToken401Response{}, err
}
log.Printf("got auth token: %s", token)
ext_service, err := s.db.GetExternalServiceByToken(context.Background(), &token)
if err != nil {
log.Errorf("failed to get external service by token: %v", err)
return auth.GetImpersonationToken401Response{}, err
// TODO: check err and retyrn 400/500
}
// TODO: handle tgid
accessToken, err := s.generateImpersonationToken(fmt.Sprintf("%d", *req.Body.UserId), fmt.Sprintf("%d", ext_service.ID))
if err != nil {
log.Errorf("failed to generate impersonation token: %v", err)
return auth.GetImpersonationToken401Response{}, err
// TODO: check err and retyrn 400/500
}
return auth.GetImpersonationToken200JSONResponse{AccessToken: accessToken}, nil
}
// func (s Server) PostAuthVerifyToken(ctx context.Context, req auth.PostAuthVerifyTokenRequestObject) (auth.PostAuthVerifyTokenResponseObject, error) {
// valid := false
// var userID *string
@ -236,3 +285,11 @@ func (s Server) PostSignIn(ctx context.Context, req auth.PostSignInRequestObject
// Error: errStr,
// }, nil
// }
func ExtractBearerToken(header string) (string, error) {
const prefix = "Bearer "
if len(header) <= len(prefix) || header[:len(prefix)] != prefix {
return "", fmt.Errorf("invalid bearer token format")
}
return header[len(prefix):], nil
}

View file

@ -9,3 +9,7 @@ INTO users (passhash, nickname)
VALUES (sqlc.arg(passhash), sqlc.arg(nickname))
RETURNING id;
-- name: GetExternalServiceByToken :one
SELECT *
FROM external_services
WHERE auth_token = sqlc.arg('auth_token');