Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions docs/en/02-configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,6 @@ HTTP server CORS config. If not set, no CORS settings will be applied.

If set to non-empty string, JWT provider is created for API tokens verification.

> API tokens allow access only for [`/seqapi/*`, `/massexport/*`] routes in HTTP API and [`SeqAPIService`, `MassExportService`] service in gRPC API. For other routes/services requiring auth, OIDC check will be performed, so `jwt_secret_key` should be used in pair with `oidc`.

**`oidc`** *`OIDC`* *`optional`*

Open ID Connect config. If not set, no OIDC verification will be applied.
Expand Down
2 changes: 0 additions & 2 deletions docs/ru/02-configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,6 @@ server:

Если задана непустая строка, то создается JWT-провайдер для верификации токенов.

> Авторизация по токенам разрешена только для обработчиков [`/seqapi/*`, `/massexport/*`] в HTTP API и сервисам [`SeqAPIService`, `MassExportService`] в gRPC API. Для других обработчиков/сервисов, требующих авторизацию, будет использоваться OIDC, поэтому `jwt_secret_key` следует использовать в паре с `oidc`.

**`oidc`** *`OIDC`* *`optional`*

Конфигурация Open ID Connect. Если не задано, то верификации по OIDC не будет.
Expand Down
13 changes: 2 additions & 11 deletions internal/app/mw/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,6 @@ import (

var errAuthProviderNotInit = errors.New("auth provider was not initialized")

var (
tokenAuthServices = map[string]struct{}{
"seqapi": {},
"massexport": {},
"SeqAPIService": {},
"MassExportService": {},
}
)

const authHeaderBearerKey = "Bearer"

func getTokenFromAuthHeader(authHeader string) (string, error) {
Expand Down Expand Up @@ -64,12 +55,12 @@ func NewAuthProviders(
return authPrvds, nil
}

func (p *AuthProviders) auth(ctx context.Context, authHeader string, checkAPIToken bool) (string, error) {
func (p *AuthProviders) auth(ctx context.Context, authHeader string) (string, error) {
token, err := getTokenFromAuthHeader(authHeader)
if err != nil {
return "", fmt.Errorf("failed to get token from auth header: %w", err)
}
if checkAPIToken && p.JwtProvider != nil {
if p.JwtProvider != nil {
// first check if token was issued by the app's JWT provider
jwtClaims, err := p.JwtProvider.Verify(token)
if err == nil {
Expand Down
77 changes: 18 additions & 59 deletions internal/app/mw/auth_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,8 @@ func TestAuthProvidersAuth(t *testing.T) {
tCases := []struct {
name string

authHeader string
checkAPIToken bool
mockArgs mockArgs
authHeader string
mockArgs mockArgs

want string
wantErr bool
Expand All @@ -59,9 +58,8 @@ func TestAuthProvidersAuth(t *testing.T) {
wantErr: true,
},
{
name: "ok_jwt_only",
authHeader: authHeader,
checkAPIToken: true,
name: "ok_jwt_only",
authHeader: authHeader,
mockArgs: mockArgs{
jwt: &jwtMockArgs{
token: token,
Expand All @@ -71,9 +69,8 @@ func TestAuthProvidersAuth(t *testing.T) {
want: formatJWTServiceName(userName),
},
{
name: "err_jwt_only",
authHeader: authHeader,
checkAPIToken: true,
name: "err_jwt_only",
authHeader: authHeader,
mockArgs: mockArgs{
jwt: &jwtMockArgs{
token: token,
Expand All @@ -83,9 +80,8 @@ func TestAuthProvidersAuth(t *testing.T) {
wantErr: true,
},
{
name: "ok_oidc_only",
authHeader: authHeader,
checkAPIToken: true,
name: "ok_oidc_only",
authHeader: authHeader,
mockArgs: mockArgs{
oidc: &oidcMockArgs{
token: token,
Expand All @@ -95,9 +91,8 @@ func TestAuthProvidersAuth(t *testing.T) {
want: userName,
},
{
name: "err_oidc_only",
authHeader: authHeader,
checkAPIToken: true,
name: "err_oidc_only",
authHeader: authHeader,
mockArgs: mockArgs{
oidc: &oidcMockArgs{
token: token,
Expand All @@ -107,15 +102,13 @@ func TestAuthProvidersAuth(t *testing.T) {
wantErr: true,
},
{
name: "err_no_providers",
authHeader: authHeader,
checkAPIToken: true,
wantErr: true,
name: "err_no_providers",
authHeader: authHeader,
wantErr: true,
},
{
name: "err_jwt_ok_oidc",
authHeader: authHeader,
checkAPIToken: true,
name: "err_jwt_ok_oidc",
authHeader: authHeader,
mockArgs: mockArgs{
jwt: &jwtMockArgs{
token: token,
Expand All @@ -128,38 +121,6 @@ func TestAuthProvidersAuth(t *testing.T) {
},
want: userName,
},
{
name: "ok_oidc_skip_check_api_token",
authHeader: authHeader,
checkAPIToken: false,
mockArgs: mockArgs{
jwt: &jwtMockArgs{
token: token,
jwtClaims: jwtClaims,
},
oidc: &oidcMockArgs{
token: token,
oidcToken: oidcToken,
},
},
want: userName,
},
{
name: "err_oidc_skip_check_api_token",
authHeader: authHeader,
checkAPIToken: false,
mockArgs: mockArgs{
jwt: &jwtMockArgs{
token: token,
jwtClaims: jwtClaims,
},
oidc: &oidcMockArgs{
token: token,
err: err,
},
},
wantErr: true,
},
}

for _, tCase := range tCases {
Expand All @@ -172,10 +133,8 @@ func TestAuthProvidersAuth(t *testing.T) {
authPrv := &AuthProviders{}
if tCase.mockArgs.jwt != nil {
jwtProvider := mock_auth.NewMockJWTProvider(ctrl)
if tCase.checkAPIToken {
jwtProvider.EXPECT().Verify(tCase.mockArgs.jwt.token).
Return(tCase.mockArgs.jwt.jwtClaims, tCase.mockArgs.jwt.err)
}
jwtProvider.EXPECT().Verify(tCase.mockArgs.jwt.token).
Return(tCase.mockArgs.jwt.jwtClaims, tCase.mockArgs.jwt.err)

authPrv.JwtProvider = jwtProvider
}
Expand All @@ -187,7 +146,7 @@ func TestAuthProvidersAuth(t *testing.T) {
authPrv.OidcProvider = oidcProvider
}

got, err := authPrv.auth(context.Background(), authHeader, tCase.checkAPIToken)
got, err := authPrv.auth(context.Background(), authHeader)
require.Equal(t, tCase.wantErr, err != nil)
if tCase.wantErr {
return
Expand Down
3 changes: 1 addition & 2 deletions internal/app/mw/grpc_mw.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,8 +157,7 @@ func GRPCAuthInterceptor(providers *AuthProviders) grpc.UnaryServerInterceptor {
logger.Error("no authorization metadata provided")
return nil, errUnauth
}
_, checkAPIToken := tokenAuthServices[svc]
userName, err := providers.auth(ctx, authHeaderSlice[0], checkAPIToken)
userName, err := providers.auth(ctx, authHeaderSlice[0])
if err != nil {
logger.Error("token auth failed", zap.Error(err))
return nil, errUnauth
Expand Down
11 changes: 1 addition & 10 deletions internal/app/mw/http_mw.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,17 +161,8 @@ func HTTPAuthInterceptor(providers *AuthProviders) func(next http.Handler) http.
return
}

uriApi, _, _, err := parseURI(r.RequestURI)
if err != nil {
msg := "failed to parse URI"
logger.Error(msg, zap.Error(err))
http.Error(w, msg, http.StatusInternalServerError)
return
}

authHeader := r.Header.Get("Authorization")
_, checkAPIToken := tokenAuthServices[uriApi]
username, err := providers.auth(ctx, authHeader, checkAPIToken)
username, err := providers.auth(ctx, authHeader)
if err != nil {
logger.Error("token auth failed", zap.Error(err))
http.Error(w, "Unauthenticated", http.StatusUnauthorized)
Expand Down
Loading