This library provide user login/registration feature based on cookie JWT token with multiple storage support.
- Registration
- Login
- JWT token via cookie
- XSRF protection
- Out of the box HTML templates read to use
- Or use it only as a backend with your own frontend
- Confirmation token
- Multiple router supports (Gin, standard, etc.)
- Multiple storage supports (Mysql, Postgres, config, "create your own", ...)
With Gin (Routers):
func main() {
configPath := "./default.yml"
auth, err := authless.NewGinAuth(configPath)
if err != nil {
log.Println(err)
return
}
auth.SetTokenSender(func(email, token string) error {
fmt.Println("TOKEN SEND", token)
return nil
})
router := gin.Default()
auth.InitServiceRoutes(router)
router.GET("/ping", func(c *gin.Context) {
c.String(200, "pong")
})
router.Handle("GET", "/private", auth.AuthRequired(func(c *gin.Context) {
c.String(200, "private")
}))
router.GET("/public", func(c *gin.Context) {
c.String(200, "public")
})
log.Fatal(http.ListenAndServe(":8080", router))
}
You can create config object in code:
config := &authless.Config{
Host: "example.com", // this will used for activation/forget-password links
Secret: "d123",
DisableXSRF: true,
TokenDuration: time.Minute,
CookieDuration: time.Minute,
Storage: storage.Config{
Type: "mysql", // mysql, const (setup by config), postgres, inmemory
Host: "localhost",
Port: 3306,
Username: "user",
Password: "pass",
Dbname: "myusers",
},
Type: authless.AuthTypeTemplate, // 'template' or 'api'
LogLevel: "debug", // debug, info, warning, error
TemplatePath: "", // path to template folder
Validator: nil,
}
or parse it from yaml:
path := "./default.yml"
conf, err := authless.ReadConfig(path)
Caveat: yaml parser property names are case-insensitive
There are ready to use html login/registration forms. To use it
copy template
folder to your project root.
We recommend to use Gin as main router.
To create new auth
:
auth, err := authless.NewGorillaAuth(conf)
To add service routes:
router := gin.Default()
auth.InitServiceRoutes(router)
If you need to restrict unauthorized access to route wrap handler with AuthRequired
:
router.Handle("GET", "/private", auth.AuthRequired(func(c *gin.Context) {
c.String(200, "private")
}))
Don't forget to setup password change and password forget:
auth.SetActivationTokenSenderFunc(func(email, token string) error {
fmt.Println("TOKEN SEND", token)
return nil
})
auth.SetChangePasswordRequestFunc(func(email, token string) error {
fmt.Println("TOKEN SEND", token)
return nil
})
Adapter for Gorilla router Use it in the same way as Gin, except creating:
auth, err := authless.NewGorillaAuth(conf)
Call GET /auth/[email protected]&passwd=xyz
or send POST form
{
"email": "[email protected]",
"password": "xyz"
}
Call GET /auth/logout
to remove cookie and blacklist token (see todo)
Send POST form /auth/register
{
"email": "[email protected]",
"password": "xyz"
}
to create new user. Created user is not active and unable to login.
Use ActivateAccountFunc = func(email, url, token string) error
to send token during registration
Example:
auth, _ := authless.NewGinAuth(configPath)
client := NewMailerClient(somekey)
auth.SetActivationTokenSenderFunc(func(email, activateUrl, token string) error {
//make user go to activateUrl to activate accoung
return client.SendEmail(email, token)
})
Call GET /auth/activate?token=mytoken
to activate account to able account to login
To send change password send POST form to /auth/forget-password
:
{
"email": "[email protected]",
}
This will generate new token and execute ChangePasswordRequestFunc
Use:
type ChangePasswordRequestFunc = func(email, token string) error
Example:
auth, _ := authless.NewGinAuth(configPath)
client := NewMailerClient(somekey)
auth.SetChangePasswordRequestFunc(func(email, url, token string) error {
return client.SendChangePassword
})
To change password send POST form to /auth/change-password
{
"email": "[email protected]",
"token": "TOKEN", //TOKEN sent by ChangePasswordRequestFunc
"password": "newpassword",
}
To override page:
- create your own html page
- insert Vars into your template. Under Var message or error text will be displayed
- rename html and put under Template path
- template will be available under Path
List of available routes:
Path: /login
Template path: template/login_form.html
Vars: {{.error}}
Path: /logout
Template path: -
Path: /register
Template path: template/registration_form.html
Vars: {{.error}}
Path: /register/result
Template path: template/registration_form.html
Vars: {{.message}}
Path: /activate/result
Template: template/activation_result.html
Vars: {{.error}}
{{.message}}
Description: display form for password remind
Path: /forget-password
Template: template/forget_password_form.html
Vars: {{.error}}
Description: page to show after successfully remind password submission
Path: /forget-password/result
Template: template/forget_password_result.html
Vars: {{.error}}
{{.message}}
Description: display change password form
Path: /change-password
Template: template/change_password_form.html
Vars: {{.error}}
Description: page to show after successfully change password submission
Path: /change-password/result
Template: template/change_password_result.html
Vars: {{.error}}
{{.message}}
- Add tests
- Add gorilla http router
- Add default http router
- Forget password mux
- Forget password gorilla
- Get rid of /r/
- Add global auth.GetUser method
- Fully get rid of authz package
- Load default html template
- Validate html present
- Finish README
- Add postgres
- Validate config
- Pass full url to forget pass/validate acc functions
- Blacklist of expired tokens (after logout token invalid)
- Get rid of error message in query ?error=bad request
- Routes as const
- Min config to start: storage only
- Check successurl
- Add "Activate password" callback
- Audit log