AuthBricks
AuthBricks is a Go library for building Identity and Access Management solutions. It aims to provide simple primitives and APIs that comply with the best practices in the industry, while remaining flexible enough to be used in a wide range of use cases.
At the moment it implements the following RFCs (planning to get to full OIDC compliance):
- OAuth 2.0 Authorization Code Grant (RFC 6749)
- OAuth 2.0 Client Credentials Grant (RFC 6749)
- OAuth 2.0 Refresh Token Grant (RFC 6749)
- OIDC Hybrid Flow (OIDC Core 1.0)
- PKCE Support (RFC 7636)
- JSON Web Token (JWT) Profile for OAuth 2.0 Access Tokens (RFC 9068)
Get Started
Postgres
Connect to a local postgres database, and start the API server on port 8080.
package main
import (
"context"
"go.authbricks.com/bricks/api"
"go.authbricks.com/bricks/database"
)
func main() {
db, err := database.NewPostgres(context.Background(), "postgres://user:password@localhost:5432/db")
if err != nil {
panic(err)
}
a, err := api.New(db)
if err != nil {
panic(err)
}
a.ListenAndServe(":8080")
}
MySQL
Connect to a local MySQL database, and start the API server on port 8080.
package main
import (
"context"
"go.authbricks.com/bricks/api"
"go.authbricks.com/bricks/database"
)
func main() {
db, err := database.NewMySQL(context.Background(), "user:password@tcp(localhost:3306)/db")
if err != nil {
panic(err)
}
a, err := api.New(db)
if err != nil {
panic(err)
}
a.ListenAndServe(":8080")
}
SQLite
Connect to a SQLite database, and start the API server on port 8080.
package main
import (
"context"
"go.authbricks.com/bricks/api"
"go.authbricks.com/bricks/database"
)
func main() {
db, err := database.NewSQLite(context.Background(), "file:file.db?_fk=1")
if err != nil {
panic(err)
}
a, err := api.New(db)
if err != nil {
panic(err)
}
a.ListenAndServe(":8080")
}
Define a new Service
All the examples so far have simply started the API server on port 8080. The server does not actually have any endpoints yet. In this section, we will define a new service.
In terms of OAuth / OIDC specifications, you can think of a service
as your Authorization server.
For example, if your business needs to authenticate both your customers and your employees, you could define
two different services called customers
and employees
.
serviceConfig := config.Service{
Name: "customers",
Identifier: "customers",
Description: "Service for authenticating customers",
ServiceMetadata: config.ServiceMetadata{
"foo": "bar",
},
AllowedClientMetadata: []string{"baz"},
Scopes: []string{"read", "write"},
GrantTypes: []string{config.GrantTypeAuthorizationCode, config.GrantTypeRefreshToken},
ResponseTypes: []string{"code"},
}
svc, err := db.CreateOrUpdateService(context.Background(), serviceConfig)
if err != nil {
panic(err)
}
Define an Application
Once you have defined a service, you can create a new application (also known as OAuth Client) for that service.
svc, err := db.GetService(context.Background(), "customers")
if err != nil {
panic(err)
}
appConfig := config.Application{
Name: "myapp",
RedirectURIs: []string{"http://localhost:8080/callback"},
GrantTypes: []string{config.GrantTypeAuthorizationCode, config.GrantTypeRefreshToken},
ResponseTypes: []string{config.ResponseTypeCode},
Scopes: []string{"read", "write"},
}
app, err := svc.CreateOrUpdateApplication(context.Background(), appConfig)
if err != nil {
panic(err)
}
Credentials
Once you have created an application, you can generate credentials for it.
app, err := db.GetApplication(context.Background(), "myapp")
if err != nil {
panic(err)
}
credentialsConfig := config.Credentials{
ClientID: crypto.GenerateClientID(),
ClientSecret: crypto.GenerateClientSecret(),
}
creds, err := app.CreateOrUpdateCredentials(context.Background(), credentialsConfig)
if err != nil {
panic(err)
}
Errors
The Kittn API uses the following error codes:
4xx
Error Code | Meaning |
---|---|
400 | Bad Request – Your request sucks |
401 | Unauthorized – Your API key is wrong |
403 | Forbidden – The kitten requested is hidden for administrators only |
404 | Not Found – The specified kitten could not be found |
405 | Method Not Allowed – You tried to access a kitten with an invalid method |
406 | Not Acceptable – You requested a format that isn’t json |
410 | Gone – The kitten requested has been removed from our servers |
418 | I’m a teapot |
429 | Too Many Requests – You’re requesting too many kittens! Slow down! |
5xx
Error Code | Meaning |
---|---|
500 | Internal Server Error – We had a problem with our server. Try again later. |
503 | Service Unavailable – We’re temporarily offline for maintenance. Please try again later. |
Get a Specific Kitten
package main
import "github.com/bep/kittn/auth"
func main() {
api := auth.Authorize("meowmeowmeow")
ßßß
_ = api.GetKitten(2)
}
```ruby
require 'kittn'
api = Kittn::APIClient.authorize!('meowmeowmeow')
api.kittens.get(2)
import kittn
api = kittn.authorize('meowmeowmeow')
api.kittens.get(2)
curl "http://example.com/api/kittens/2"
-H "Authorization: meowmeowmeow"
const kittn = require('kittn');
let api = kittn.authorize('meowmeowmeow');
let max = api.kittens.get(2);
The above command returns JSON structured like this:
{
"id": 2,
"name": "Max",
"breed": "unknown",
"fluffiness": 5,
"cuteness": 10
}
This endpoint retrieves a specific kitten.
HTTP Request
GET http://example.com/api/kittens/<ID>
URL Parameters
Parameter | Description |
---|---|
ID | The ID of the kitten to retrieve |