Skip to content

Commit

Permalink
Merge pull request #30 from EringiShimeji/auth/auth-interceptor
Browse files Browse the repository at this point in the history
エンドポイントの保護
  • Loading branch information
harsssh authored Aug 26, 2024
2 parents eb454eb + 1e143bd commit 8036eaf
Show file tree
Hide file tree
Showing 9 changed files with 230 additions and 1 deletion.
101 changes: 101 additions & 0 deletions backend/app/gen/sudoku/common/v1/options.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions backend/app/handler/auth/callback_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ func (h *CallbackHandler) Handle(w http.ResponseWriter, r *http.Request) {
http.SetCookie(w, &http.Cookie{
Name: SessionCookieName,
Value: output.SessionID,
Path: "/",
Secure: false, // NOTE: true が望ましいが, 開発環境で支障が出そう
HttpOnly: true,
SameSite: http.SameSiteStrictMode,
Expand Down
1 change: 1 addition & 0 deletions backend/app/handler/auth/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ func (h *Handler) SignIn(ctx context.Context, req *connect.Request[authv1.SignIn
cookies = append(cookies, &http.Cookie{
Name: "state_jwt",
Value: output.StateJWT,
Path: "/",
HttpOnly: true,
})

Expand Down
62 changes: 62 additions & 0 deletions backend/app/handler/interceptor/auth.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package interceptor

import (
"connectrpc.com/connect"
"context"
"errors"
"github.com/google/uuid"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/types/descriptorpb"
"log"
commonv1 "sudoku/gen/sudoku/common/v1"
authH "sudoku/handler/auth"
authS "sudoku/service/auth"
)

// TODO: streaming の場合は別の interceptor が必要かも
func NewAuthInterceptor(authService authS.IAuthService) connect.UnaryInterceptorFunc {
interceptor := func(next connect.UnaryFunc) connect.UnaryFunc {
return connect.UnaryFunc(func(
ctx context.Context,
req connect.AnyRequest,
) (connect.AnyResponse, error) {
methodDesc, ok := req.Spec().Schema.(protoreflect.MethodDescriptor)
if !ok {
return nil, connect.NewError(connect.CodeInternal, errors.New("invalid method descriptor"))
}
opts := methodDesc.Options().(*descriptorpb.MethodOptions)
requireAuth, ok := proto.GetExtension(opts, commonv1.E_RequireAuth).(bool)
if !ok {
return nil, connect.NewError(connect.CodeInternal, errors.New("invalid method option"))
}

log.Println("requireAuth", requireAuth)

if requireAuth {
sessionCookie := req.Header().Get(authH.SessionCookieName)
if sessionCookie == "" {
return nil, connect.NewError(connect.CodeUnauthenticated, errors.New("missing session cookie"))
}
sessionID, err := uuid.Parse(sessionCookie)
if err != nil {
return nil, connect.NewError(connect.CodeUnauthenticated, errors.New("invalid session cookie"))
}

output, err := authService.ValidateSession(authS.ValidateSessionInput{
SessionID: sessionID,
})
if err != nil {
return nil, connect.NewError(connect.CodeInternal, err)
}

if !output.IsValid {
return nil, connect.NewError(connect.CodeUnauthenticated, errors.New("invalid session"))
}
}

return next(ctx, req)
})
}
return connect.UnaryInterceptorFunc(interceptor)
}
6 changes: 5 additions & 1 deletion backend/app/server/route/register.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package route

import (
"connectrpc.com/connect"
"log"
"net/http"
"sudoku/config"
"sudoku/gen/sudoku/auth/v1/authv1connect"
authH "sudoku/handler/auth"
"sudoku/handler/interceptor"
authI "sudoku/infra/auth"
gormRepo "sudoku/infra/gorm"
authS "sudoku/service/auth"
Expand Down Expand Up @@ -39,6 +41,8 @@ func Register(mux *http.ServeMux) {
authCallbackHandler := authH.NewCallbackHandler(authService)

// register handlers
mux.Handle(authv1connect.NewAuthServiceHandler(authHandler))
interceptors := connect.WithInterceptors(interceptor.NewAuthInterceptor(authService))

mux.Handle(authv1connect.NewAuthServiceHandler(authHandler, interceptors))
mux.HandleFunc("/auth/github/callback", authCallbackHandler.Handle)
}
25 changes: 25 additions & 0 deletions frontend/lib/gen/sudoku/common/v1/options.pb.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//
// Generated code. Do not modify.
// source: sudoku/common/v1/options.proto
//
// @dart = 2.12

// ignore_for_file: annotate_overrides, camel_case_types, comment_references
// ignore_for_file: constant_identifier_names, library_prefixes
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import

import 'dart:core' as $core;

import 'package:protobuf/protobuf.dart' as $pb;

class Options {
static final requireAuth = $pb.Extension<$core.bool>(_omitMessageNames ? '' : 'google.protobuf.MethodOptions', _omitFieldNames ? '' : 'requireAuth', 50000, $pb.PbFieldType.OB);
static void registerAllExtensions($pb.ExtensionRegistry registry) {
registry.add(requireAuth);
}
}


const _omitFieldNames = $core.bool.fromEnvironment('protobuf.omit_field_names');
const _omitMessageNames = $core.bool.fromEnvironment('protobuf.omit_message_names');
11 changes: 11 additions & 0 deletions frontend/lib/gen/sudoku/common/v1/options.pbenum.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
//
// Generated code. Do not modify.
// source: sudoku/common/v1/options.proto
//
// @dart = 2.12

// ignore_for_file: annotate_overrides, camel_case_types, comment_references
// ignore_for_file: constant_identifier_names, library_prefixes
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import

15 changes: 15 additions & 0 deletions frontend/lib/gen/sudoku/common/v1/options.pbjson.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//
// Generated code. Do not modify.
// source: sudoku/common/v1/options.proto
//
// @dart = 2.12

// ignore_for_file: annotate_overrides, camel_case_types, comment_references
// ignore_for_file: constant_identifier_names, library_prefixes
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import

import 'dart:convert' as $convert;
import 'dart:core' as $core;
import 'dart:typed_data' as $typed_data;

9 changes: 9 additions & 0 deletions proto/sudoku/common/v1/options.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
syntax = "proto3";

package sudoku.common.v1;

import "google/protobuf/descriptor.proto";

extend google.protobuf.MethodOptions {
bool require_auth = 50000;
}

0 comments on commit 8036eaf

Please sign in to comment.