180 lines
4.5 KiB
Go
180 lines
4.5 KiB
Go
package mtinfo
|
|
|
|
import (
|
|
"context"
|
|
"crypto/rsa"
|
|
"errors"
|
|
"fmt"
|
|
|
|
"github.com/dgrijalva/jwt-go.git"
|
|
|
|
"google.golang.org/grpc"
|
|
"google.golang.org/grpc/metadata"
|
|
auth "src.dualinventive.com/go/authentication-service/grpc"
|
|
)
|
|
|
|
//grpcAuthServiceClient contains authentication related operations over GRPC
|
|
type grpcAuthServiceClient struct {
|
|
client auth.AuthenticationServiceClient
|
|
publicKey *rsa.PublicKey
|
|
userAgent string
|
|
}
|
|
|
|
func (as *grpcAuthServiceClient) Login(username, companyCode, password string) (string, error) {
|
|
ctx := as.withContext("")
|
|
in := &auth.LoginRequest{Credentials: &auth.Credentials{
|
|
Username: username,
|
|
CompanyCode: companyCode,
|
|
Password: password,
|
|
}}
|
|
|
|
resp, err := as.client.Login(ctx, in)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
return resp.Token.Secret, nil
|
|
}
|
|
|
|
func (as *grpcAuthServiceClient) Logout(token string) error {
|
|
ctx := as.withContext(token)
|
|
in := &auth.Empty{}
|
|
|
|
_, err := as.client.Logout(ctx, in)
|
|
return err
|
|
}
|
|
|
|
func (as *grpcAuthServiceClient) Me(token string) (*User, error) {
|
|
ctx := as.withContext(token)
|
|
in := &auth.Empty{}
|
|
|
|
resp, err := as.client.Me(ctx, in)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
user := newUser(resp.User)
|
|
|
|
return &user, nil
|
|
}
|
|
|
|
func (as *grpcAuthServiceClient) RequestPasswordReset(username string) error {
|
|
in := &auth.RequestPasswordResetRequest{
|
|
UserName: username,
|
|
}
|
|
|
|
_, err := as.client.RequestPasswordReset(context.Background(), in)
|
|
return err
|
|
}
|
|
|
|
func (as *grpcAuthServiceClient) RedeemPasswordReset(username, resetCode, password, passwordVerify string) error {
|
|
in := &auth.RedeemPasswordResetRequest{
|
|
UserName: username,
|
|
ResetCode: resetCode,
|
|
Password: password,
|
|
PasswordVerify: passwordVerify,
|
|
}
|
|
|
|
_, err := as.client.RedeemPasswordReset(context.Background(), in)
|
|
return err
|
|
}
|
|
|
|
func (as *grpcAuthServiceClient) ListTokens(token string) (OpaqueTokens, error) {
|
|
ctx := as.withContext(token)
|
|
in := &auth.Empty{}
|
|
|
|
resp, err := as.client.ListTokens(ctx, in)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return newOpaqueTokens(resp.Tokens), nil
|
|
}
|
|
|
|
func (as *grpcAuthServiceClient) DeleteToken(token string, opaqueToken string) error {
|
|
ctx := as.withContext(token)
|
|
in := &auth.DeleteTokenRequest{
|
|
OpaqueId: opaqueToken,
|
|
}
|
|
|
|
_, err := as.client.DeleteToken(ctx, in)
|
|
return err
|
|
}
|
|
|
|
//VerifyToken verifies the given token to see if its valid.
|
|
//When a public key is configured, token is locally verified using JWT.
|
|
//When no public key is configured, token is remotely verified using GRPC.
|
|
//Returns false when token signed portion is invalid, or token is expired.
|
|
func (as *grpcAuthServiceClient) VerifyToken(token string, rights ...string) (bool, error) {
|
|
if as.publicKey != nil {
|
|
var claims Claims
|
|
tkn, err := jwt.ParseWithClaims(token, &claims, func(token *jwt.Token) (interface{}, error) {
|
|
return as.publicKey, nil
|
|
})
|
|
if err != nil {
|
|
return false, fmt.Errorf("error parsing jwt token: %s", err.Error())
|
|
}
|
|
return tkn.Valid && claims.Rights.containsAll(rights...), nil
|
|
}
|
|
|
|
return as.VerifyTokenRemotely(token, rights...)
|
|
}
|
|
|
|
//VerifyTokenRemotely verifies the given token to see if its valid.
|
|
//Token is remotely verified using GRPC.
|
|
//Returns false when token signed portion is invalid, or token is expired.
|
|
func (as *grpcAuthServiceClient) VerifyTokenRemotely(token string, rights ...string) (bool, error) {
|
|
ctx := as.withContext(token)
|
|
in := &auth.VerifyTokenRequest{Rights: rights}
|
|
|
|
resp, err := as.client.VerifyToken(ctx, in)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
return resp.Valid, nil
|
|
}
|
|
|
|
func (as *grpcAuthServiceClient) UserAgent() string {
|
|
return as.userAgent
|
|
}
|
|
|
|
func (as *grpcAuthServiceClient) SetUserAgent(userAgent string) {
|
|
as.userAgent = userAgent
|
|
}
|
|
|
|
func (as *grpcAuthServiceClient) withContext(token string) context.Context {
|
|
md := metadata.Pairs(
|
|
"token", token,
|
|
"userAgent", as.userAgent,
|
|
)
|
|
ctx := metadata.NewOutgoingContext(context.Background(), md)
|
|
return ctx
|
|
}
|
|
|
|
func newGrpcAuthServiceClient(host, port string, publicKeyPath string) (AuthServiceClient, error) {
|
|
client := &grpcAuthServiceClient{
|
|
userAgent: "grpc",
|
|
}
|
|
if host == "" {
|
|
return nil, errors.New("host not configured")
|
|
}
|
|
if port == "" {
|
|
return nil, errors.New("port not configured")
|
|
}
|
|
if publicKeyPath != "" {
|
|
publicKey, err := configurePublicKey(publicKeyPath)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("invalid public key: %s", err.Error())
|
|
}
|
|
client.publicKey = publicKey
|
|
}
|
|
|
|
conn, err := grpc.Dial(fmt.Sprintf("%s:%s", host, port), grpc.WithInsecure())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
client.client = auth.NewAuthenticationServiceClient(conn)
|
|
return client, nil
|
|
}
|