Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update readme #2

Merged
merged 3 commits into from
Dec 29, 2024
Merged
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
89 changes: 86 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -2,9 +2,92 @@

[![Go Reference](https://pkg.go.dev/badge/github.com/go-phings/umbrella.svg)](https://pkg.go.dev/github.com/go-phings/umbrella) [![Go Report Card](https://goreportcard.com/badge/github.com/go-phings/umbrella)](https://goreportcard.com/report/github.com/go-phings/umbrella)

Package umbrella is meant to work as a authentication mechanism for HTTP endpoint. It can be used to wrap HTTP server handler and check if any user has been logged in. In addition to that, module serves its own endpoints for registration, activations, login and logout.
Package umbrella provides a simple authentication mechanism for an HTTP endpoint. With it, you can wrap any endpoint that should have its access restricted. In addition, it provides additional its own handler for registering new user, activating it and, naturally, signing in and out.

## Example usage
> ⚠️ The project is in beta, under heavy construction, and may introduce breaking changes in releases before `v1.0.0`.

Have a butcher's at `main_test.go` to see a sample usage.
## Table of Contents

1. [Sample code](#sample-code)
2. [Database connection](#database-connection)
3. [User model](#user-model)
4. [Features + Roadmap](#features)
5. [Motivation](#motivation)

## Sample code
The following code snippet shows how the module can be used.

```go
// database connection
dbConn, _ = sql.Open("postgres", "host=localhost user=myuser password=mypass port=5432 dbname=mydb sslmode=disable")

// umbrella controller
u := NewUmbrella(dbConn, "tblprefix_", &JWTConfig{
Key: "SomeSecretKey--.",
Issuer: "SomeIssuer",
ExpirationMinutes: 15,
}, nil)

// create db tables
_ := u.CreateDBTables()

// http server
// uri with registration, activation, login (returns auth token), logout endpoint
http.Handle("/umbrella/", u.GetHTTPHandler("/umbrella/"))
// restricted stuff that requires signing in (a token in http header)
http.Handle("/restricted_stuff/", u.GetHTTPHandlerWrapper(
getRestrictedStuffHTTPHandler(),
umbrella.HandlerConfig{},
))
http.ListenAndServe(":8001", nil)

// wrap http handler with a check for logged user
func getRestrictedStuffHTTPHandler() http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
userID := umbrella.GetUserIDFromRequest(r)
if userID != 0 {
w.WriteHeader(http.StatusOK)
w.Write([]byte("RestrictedAreaContent"))
} else {
w.WriteHeader(http.StatusUnauthorized)
w.Write([]byte("NoAccess"))
}
})
}
```

## Database connection
The module needs to store users and sessions in the database. If not attached otherwise, [struct-db-postgres](https://github.com/go-phings/struct-db-postgres) will be used as an ORM by default.

To attach a custom ORM, it needs to implement the `ORM` interface. In the `orm.go` file, there is an example on how the previously mentioned DB module is wrapped in a struct that has all the methods required by `ORM` interface.
Pass `&UmbrellaConfig` instance with `ORM` field to the `NewUmbrella` constructor to attach your object.

## User model
Umbrella comes with its own `User` and `Session` structs. However, there might be a need to use a different user model containing more fields, with a separate ORM. Hence, similarily to previous paragraph, an interface called `UserInterface` has been defined. A custom user struct must implement that interface's methods.

To do the above:
1. set `NoUserConstructor` to true in the `&UmbrellaConfig` argument when calling `NewUmbrella`
2. create new `&umbrella.Interfaces` object with `User` field and attach it to `Interfaces` field of umbrella controller.

## Features
- [X] Wrapper support for any HTTP handler
- [X] Data storage in PostgreSQL database by default
- [X] Customisable database driver and ORM
- [X] Flexible User model
- [X] Optional endpoints for sign-in (creating session objects with access tokens) and sign-out (deactivating sessions and tokens)
- [X] Optional endpoints for user registration and activation
- [X] Hooks triggered after successful actions like registration or sign-in
- [X] Option to use cookies instead of the authorisation header
- [X] Support for redirection headers after successful or failed sign-in attempts
- [X] User struct validation during user registration
- [X] Customisable tag names for field validation

### Roadmap
- [ ] Simple permission system

## Motivation
While building a backend REST API for a colleague in retail, I needed a simple way to secure HTTP endpoints with basic authentication. The goal was straightforward: users would log in with an email and password, receive a token with an expiration time, and use it to interact with the backend API. A frontend application handled this flow.

A few months later, I was approached with a similar request, this time for an internal company application that required user registration and activation.

More recently, as I began developing a platform for prototyping where I used the code, I realised that this small yet essential piece of code could be valuable to others. And so, I decided to share it here.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -3,8 +3,8 @@ module github.com/go-phings/umbrella
go 1.23.4

require (
github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/go-phings/struct-db-postgres v0.7.0
github.com/golang-jwt/jwt v3.2.2+incompatible
github.com/google/uuid v1.6.0
github.com/lib/pq v1.10.9
github.com/ory/dockertest/v3 v3.11.0
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
@@ -17,8 +17,6 @@ github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/docker/cli v26.1.4+incompatible h1:I8PHdc0MtxEADqYJZvhBrW9bo8gawKwwenxRM7/rLu8=
github.com/docker/cli v26.1.4+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY=
@@ -35,6 +33,8 @@ github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpv
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
2 changes: 1 addition & 1 deletion internal.go
Original file line number Diff line number Diff line change
@@ -9,7 +9,7 @@ import (
"regexp"
"time"

"github.com/dgrijalva/jwt-go"
"github.com/golang-jwt/jwt"
"github.com/google/uuid"
"golang.org/x/crypto/bcrypt"
)
2 changes: 1 addition & 1 deletion umbrella.go
Original file line number Diff line number Diff line change
@@ -9,8 +9,8 @@ import (
"regexp"
"strings"

"github.com/dgrijalva/jwt-go"
sdb "github.com/go-phings/struct-db-postgres"
"github.com/golang-jwt/jwt"
"github.com/google/uuid"
"golang.org/x/crypto/bcrypt"
)