Skip to content

Commit 37fb426

Browse files
committed
Add bearer auth
1 parent 3c63e73 commit 37fb426

7 files changed

Lines changed: 91 additions & 5 deletions

File tree

api/pkg/di/container.go

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
11
package di
22

33
import (
4+
"context"
45
"fmt"
56
"io"
67
"log"
78
"os"
89
"time"
910

11+
firebase "firebase.google.com/go"
12+
"firebase.google.com/go/auth"
13+
"github.com/NdoleStudio/http-sms-manager/pkg/middlewares"
14+
"google.golang.org/api/option"
15+
1016
"github.com/gofiber/fiber/v2/middleware/cors"
1117

1218
"github.com/NdoleStudio/http-sms-manager/pkg/entities"
@@ -52,6 +58,8 @@ func NewContainer(projectID string) (container *Container) {
5258
container.RegisterHeartbeatRoutes()
5359
container.RegisterHeartbeatListeners()
5460

61+
container.RegisterUserRoutes()
62+
5563
// this has to be last since it registers the /* route
5664
container.RegisterSwaggerRoutes()
5765

@@ -75,6 +83,10 @@ func (container *Container) App() (app *fiber.App) {
7583
// Default config
7684
app.Use(cors.New())
7785

86+
app.Use(middlewares.BearerAuth(container.Logger(), container.Tracer(), container.FirebaseAuthClient()))
87+
app.Use(middlewares.APIKeyAuth(container.Logger(), container.Tracer(), container.UserRepository()))
88+
app.Use(middlewares.Authenticated(container.Tracer()))
89+
7890
container.app = app
7991
return app
8092
}
@@ -130,6 +142,34 @@ func (container *Container) DB() (db *gorm.DB) {
130142
return container.db
131143
}
132144

145+
// FirebaseApp creates a new instance of firebase.App
146+
func (container *Container) FirebaseApp() (app *firebase.App) {
147+
container.logger.Debug(fmt.Sprintf("creating %T", app))
148+
app, err := firebase.NewApp(context.Background(), nil, option.WithCredentialsJSON(container.FirebaseCredentials()))
149+
if err != nil {
150+
msg := "cannot initialize firebase application"
151+
container.logger.Fatal(stacktrace.Propagate(err, msg))
152+
}
153+
return app
154+
}
155+
156+
// FirebaseAuthClient creates a new instance of auth.Client
157+
func (container *Container) FirebaseAuthClient() (client *auth.Client) {
158+
container.logger.Debug(fmt.Sprintf("creating %T", client))
159+
authClient, err := container.FirebaseApp().Auth(context.Background())
160+
if err != nil {
161+
msg := "cannot initialize firebase auth client"
162+
container.logger.Fatal(stacktrace.Propagate(err, msg))
163+
}
164+
return authClient
165+
}
166+
167+
// FirebaseCredentials returns firebase credentials as bytes.
168+
func (container *Container) FirebaseCredentials() []byte {
169+
container.logger.Debug("creating firebase credentials")
170+
return []byte(os.Getenv("FIREBASE_CREDENTIALS"))
171+
}
172+
133173
// Tracer creates a new instance of telemetry.Tracer
134174
func (container *Container) Tracer() (t telemetry.Tracer) {
135175
container.logger.Debug("creating telemetry.Tracer")
@@ -255,6 +295,16 @@ func (container *Container) HeartbeatService() (service *services.HeartbeatServi
255295
)
256296
}
257297

298+
// UserService creates a new instance of services.UserService
299+
func (container *Container) UserService() (service *services.UserService) {
300+
container.logger.Debug(fmt.Sprintf("creating %T", service))
301+
return services.NewUserService(
302+
container.Logger(),
303+
container.Tracer(),
304+
container.UserRepository(),
305+
)
306+
}
307+
258308
// MessageThreadService creates a new instance of services.MessageService
259309
func (container *Container) MessageThreadService() (service *services.MessageThreadService) {
260310
container.logger.Debug(fmt.Sprintf("creating %T", service))
@@ -276,6 +326,16 @@ func (container *Container) MessageHandler() (handler *handlers.MessageHandler)
276326
)
277327
}
278328

329+
// UserHandler creates a new instance of handlers.MessageHandler
330+
func (container *Container) UserHandler() (handler *handlers.UserHandler) {
331+
container.logger.Debug(fmt.Sprintf("creating %T", handler))
332+
return handlers.NewUserHandler(
333+
container.Logger(),
334+
container.Tracer(),
335+
container.UserService(),
336+
)
337+
}
338+
279339
// RegisterMessageListeners registers event listeners for listeners.MessageListener
280340
func (container *Container) RegisterMessageListeners() {
281341
container.logger.Debug(fmt.Sprintf("registering listners for %T", listeners.MessageListener{}))
@@ -349,6 +409,12 @@ func (container *Container) RegisterHeartbeatRoutes() {
349409
container.HeartbeatHandler().RegisterRoutes(container.App().Group("v1"))
350410
}
351411

412+
// RegisterUserRoutes registers routes for the /users prefix
413+
func (container *Container) RegisterUserRoutes() {
414+
container.logger.Debug(fmt.Sprintf("registering %T routes", &handlers.UserHandler{}))
415+
container.UserHandler().RegisterRoutes(container.App().Group("v1"))
416+
}
417+
352418
// RegisterSwaggerRoutes registers routes for swagger
353419
func (container *Container) RegisterSwaggerRoutes() {
354420
container.logger.Debug(fmt.Sprintf("registering %T routes", &handlers.MessageHandler{}))
@@ -365,6 +431,16 @@ func (container *Container) HeartbeatRepository() repositories.HeartbeatReposito
365431
)
366432
}
367433

434+
// UserRepository registers a new instance of repositories.UserRepository
435+
func (container *Container) UserRepository() repositories.UserRepository {
436+
container.logger.Debug("creating GORM repositories.UserRepository")
437+
return repositories.NewGormUserRepository(
438+
container.Logger(),
439+
container.Tracer(),
440+
container.DB(),
441+
)
442+
}
443+
368444
func logger() telemetry.Logger {
369445
hostname, _ := os.Hostname()
370446
fields := fiber.Map{

api/pkg/handlers/heartbeat_handler.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ func (h *HeartbeatHandler) RegisterRoutes(router fiber.Router) {
5454
// @Param limit query int false "number of heartbeats to return" minimum(1) maximum(20)
5555
// @Success 200 {object} responses.HeartbeatsResponse
5656
// @Failure 400 {object} responses.BadRequest
57+
// @Failure 403 {object} responses.Unauthorized
5758
// @Failure 422 {object} responses.UnprocessableEntity
5859
// @Failure 500 {object} responses.InternalServerError
5960
// @Router /heartbeats [get]

api/pkg/handlers/message_handler.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ func (h *MessageHandler) RegisterRoutes(router fiber.Router) {
5959
// @Param payload body requests.MessageSend true "PostSend message request payload"
6060
// @Success 200 {object} responses.MessageResponse
6161
// @Failure 400 {object} responses.BadRequest
62+
// @Failure 403 {object} responses.Unauthorized
6263
// @Failure 422 {object} responses.UnprocessableEntity
6364
// @Failure 500 {object} responses.InternalServerError
6465
// @Router /messages/send [post]

api/pkg/handlers/message_thread_handler.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ func (h *MessageThreadHandler) RegisterRoutes(router fiber.Router) {
5454
// @Param limit query int false "number of messages to return" minimum(1) maximum(20)
5555
// @Success 200 {object} responses.MessageThreadsResponse
5656
// @Failure 400 {object} responses.BadRequest
57+
// @Failure 403 {object} responses.Unauthorized
5758
// @Failure 422 {object} responses.UnprocessableEntity
5859
// @Failure 500 {object} responses.InternalServerError
5960
// @Router /message-threads [get]

api/pkg/middlewares/api_key_auth_middleware.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,16 @@ import (
1111

1212
// APIKeyAuth authenticates a user from the X-API-Key header
1313
func APIKeyAuth(logger telemetry.Logger, tracer telemetry.Tracer, userRepository repositories.UserRepository) fiber.Handler {
14+
logger = logger.WithService("middlewares.APIKeyAuth")
15+
1416
return func(c *fiber.Ctx) error {
1517
ctx, span := tracer.StartFromFiberCtx(c, "middlewares.APIKeyAuth")
1618
defer span.End()
1719

1820
ctxLogger := tracer.CtxLogger(logger, span)
1921

2022
apiKey := c.Get(authHeaderAPIKey)
21-
if len(apiKey) > 0 {
23+
if len(apiKey) == 0 {
2224
span.AddEvent(fmt.Sprintf("the request header has no [%s] api key", authHeaderAPIKey))
2325
return c.Next()
2426
}
@@ -31,7 +33,7 @@ func APIKeyAuth(logger telemetry.Logger, tracer telemetry.Tracer, userRepository
3133

3234
c.Locals(ContextKeyAuthUserID, authUser)
3335

34-
ctxLogger.Info(fmt.Sprintf("[%s] set successfully for user with ID [%s]", authUser, authUser.ID))
36+
ctxLogger.Info(fmt.Sprintf("[%T] set successfully for user with ID [%s]", authUser, authUser.ID))
3537

3638
return c.Next()
3739
}

api/pkg/middlewares/bearer_auth_middleware.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414

1515
// BearerAuth authenticates a user based on the bearer token
1616
func BearerAuth(logger telemetry.Logger, tracer telemetry.Tracer, authClient *auth.Client) fiber.Handler {
17+
logger = logger.WithService("middlewares.BearerAuth")
1718
return func(c *fiber.Ctx) error {
1819
_, span := tracer.StartFromFiberCtx(c, "middlewares.BearerAuth")
1920
defer span.End()
@@ -40,12 +41,13 @@ func BearerAuth(logger telemetry.Logger, tracer telemetry.Tracer, authClient *au
4041
span.AddEvent(fmt.Sprintf("[%s] token is valid", bearerScheme))
4142

4243
authUser := entities.AuthUser{
43-
ID: entities.UserID(token.Claims["user_id"].(string)),
44+
Email: token.Claims["email"].(string),
45+
ID: entities.UserID(token.Claims["user_id"].(string)),
4446
}
4547

4648
c.Locals(ContextKeyAuthUserID, authUser)
4749

48-
ctxLogger.Info(fmt.Sprintf("[%s] set successfully for user with ID [%s]", authUser, authUser.ID))
50+
ctxLogger.Info(fmt.Sprintf("[%T] set successfully for user with ID [%s]", authUser, authUser.ID))
4951
return c.Next()
5052
}
5153
}

web/pages/threads/index.vue

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@
2626

2727
<script>
2828
export default {
29-
name: 'IndexPage',
29+
middleware: ['auth'],
30+
mounted() {
31+
this.$store.dispatch('loadThreads')
32+
},
3033
}
3134
</script>

0 commit comments

Comments
 (0)