Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
form-based auth tutorial application added
- Loading branch information
Showing
25 changed files
with
1,460 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
# aah framework application - .gitignore | ||
|
||
aah.go | ||
*.pid | ||
build/ | ||
|
||
# Compiled Object files, Static and Dynamic libs (Shared Objects) | ||
*.o | ||
*.a | ||
*.so | ||
|
||
# Folders | ||
_obj | ||
_test | ||
|
||
# Architecture specific extensions/prefixes | ||
*.[568vq] | ||
[568vq].out | ||
|
||
*.cgo1.go | ||
*.cgo2.c | ||
_cgo_defun.c | ||
_cgo_gotypes.go | ||
_cgo_export.* | ||
|
||
_testmain.go | ||
|
||
*.exe | ||
*.test | ||
*.prof |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
######################################## | ||
# form-based-auth - aah framework project | ||
# | ||
# Note: Add it to version control | ||
######################################## | ||
|
||
# Build section is used during aah application compile and build command. | ||
build { | ||
# Application binary name | ||
# Default value is `name` attribute value from `aah.conf` | ||
#binary_name = "form-based-auth" | ||
|
||
# Used as fallback if | ||
# - `git commit sha` or | ||
# - `AAH_APP_VERSION` environment value is not available. | ||
version = "0.0.1" | ||
|
||
# If application is missing any dependencies in `build import path` | ||
# during a compile and build, aah CLI will try to get dependencies | ||
# using 'go get <package>'. | ||
# Default value is `false`. | ||
#dep_get = true | ||
|
||
# Log level is used for aah CLI tool logging. | ||
# Default value is `info`. | ||
#log_level = "info" | ||
|
||
flags = ["-i"] | ||
|
||
ldflags = "" | ||
|
||
tags = "" | ||
|
||
# AST excludes is used for `aah.Context` inspection and generating aah | ||
# application main Go file. Valid exclude patterns | ||
# refer: https://golang.org/pkg/path/filepath/#Match | ||
ast_excludes = ["*_test.go", ".*", "*.bak", "*.tmp", "vendor"] | ||
|
||
# Packing excludes is used to exclude file/directory during aah application | ||
# build archive. Valid exclude patterns | ||
# refer: https://golang.org/pkg/path/filepath/#Match | ||
excludes = ["*.go", "*_test.go", ".*", "*.bak", "*.tmp", "vendor", "app", "build", "tests", "logs"] | ||
} | ||
|
||
# Watch configuration is for hot-reload. Configured files/directories are | ||
# excluded from watched file list. | ||
# Read more about hot-reload: https://github.com/go-aah/aah/issues/4 | ||
watch { | ||
# Note: static directory not required to monitored, since server delivers | ||
# update to file on environment profile `dev`. | ||
dir_excludes = [".*", "build", "static", "vendor", "tests", "logs"] | ||
|
||
file_excludes = [".*", "_test.go", "form-based-auth.pid", "aah.go", "LICENSE", "README.md"] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package admin | ||
|
||
import "aahframework.org/aah.v0" | ||
|
||
// DashboardController struct demo implementation of admin scope. | ||
type DashboardController struct { | ||
*aah.Context | ||
} | ||
|
||
// BeforeIndex method is action interceptor of Dashboard. | ||
func (a *DashboardController) BeforeIndex() { | ||
if !a.Subject().HasRole("administrator") { | ||
a.Reply().Forbidden().HTMLf("/access-denied.html", nil) | ||
a.Abort() | ||
} | ||
} | ||
|
||
// Index method dispay the admin Dashboard page. | ||
func (a *DashboardController) Index() { | ||
a.Reply().Ok() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
package controllers | ||
|
||
import ( | ||
"aahframework.org/aah.v0" | ||
"github.com/go-aah/tutorials/form-based-auth/app/models" | ||
) | ||
|
||
// AppController struct application controller | ||
type AppController struct { | ||
*aah.Context | ||
} | ||
|
||
// Index method is application home page. | ||
func (a *AppController) Index() { | ||
data := aah.Data{ | ||
"Greet": models.Greet{ | ||
Message: "Welcome to Tutorial - Form Based Auth", | ||
}, | ||
} | ||
|
||
a.Reply().Ok().HTML(data) | ||
} | ||
|
||
// BeforeLogin method action is interceptor of Login. | ||
func (a *AppController) BeforeLogin() { | ||
if a.Subject() != nil && a.Subject().IsAuthenticated() { | ||
a.Reply().Redirect(a.ReverseURL("index")) | ||
a.Abort() | ||
} | ||
} | ||
|
||
// Login method presents the login page. | ||
func (a *AppController) Login() { | ||
a.Reply().Ok() | ||
} | ||
|
||
// Logout method does logout currently logged in subject (aka user). | ||
func (a *AppController) Logout() { | ||
if a.Subject() != nil { | ||
a.Subject().Logout() | ||
} | ||
|
||
// Send it to login page | ||
a.Reply().Redirect(a.ReverseURL("login")) | ||
} | ||
|
||
// BeforeManageUsers method is action interceptor of ManageUsers. | ||
func (a *AppController) BeforeManageUsers() { | ||
// Checking role and permission | ||
subject := a.Subject() | ||
if !subject.HasAnyRole("manager", "administrator") || | ||
!subject.IsPermitted("users:manage:view") { | ||
a.Reply().Forbidden().HTMLf("/access-denied.html", nil) | ||
a.Abort() | ||
} | ||
} | ||
|
||
// ManageUsers method presents the manage user page afer verifying | ||
// Authorization | ||
func (a *AppController) ManageUsers() { | ||
// looks okay, present the page | ||
a.Reply().Ok().HTML(nil) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package models | ||
|
||
// Greet holds the greeting message. | ||
type Greet struct { | ||
Message string `json:"message"` | ||
} |
90 changes: 90 additions & 0 deletions
90
form-based-auth/app/security/form_authentication_provider.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
package security | ||
|
||
import ( | ||
"aahframework.org/aah.v0" | ||
"aahframework.org/config.v0" | ||
"aahframework.org/security.v0/authc" | ||
) | ||
|
||
// FormAuthenticationProvider struct implements `authc.Authenticator` interface. | ||
type FormAuthenticationProvider struct { | ||
// for demo purpose in-memory subject (aka user) info's | ||
users map[string]authc.AuthenticationInfo | ||
} | ||
|
||
// Init method initializes the FormAuthenticationProvider, this method gets called | ||
// during server start up. | ||
func (fa *FormAuthenticationProvider) Init(cfg *config.Config) error { | ||
|
||
// NOTE: for demo purpose I'm creating set users in the map. | ||
// Typically you will be using Database, API calls, LDAP, etc to get the Authentication | ||
// Information. | ||
|
||
fa.users = make(map[string]authc.AuthenticationInfo) | ||
|
||
// Subject 1 | ||
authcInfo1 := authc.NewAuthenticationInfo() | ||
authcInfo1.Principals = append(authcInfo1.Principals, | ||
&authc.Principal{Value: "user1@example.com", IsPrimary: true, Realm: "inmemory"}) | ||
authcInfo1.Credential = []byte(`$2y$10$2A4GsJ6SmLAMvDe8XmTam.MSkKojdobBVJfIU7GiyoM.lWt.XV3H6`) // welcome123 | ||
fa.users["user1@example.com"] = *authcInfo1 | ||
|
||
// Subject 2 | ||
authcInfo2 := authc.NewAuthenticationInfo() | ||
authcInfo2.Principals = append(authcInfo2.Principals, | ||
&authc.Principal{Value: "admin@example.com", IsPrimary: true, Realm: "inmemory"}) | ||
authcInfo2.Credential = []byte(`$2y$10$2A4GsJ6SmLAMvDe8XmTam.MSkKojdobBVJfIU7GiyoM.lWt.XV3H6`) // welcome123 | ||
fa.users["admin@example.com"] = *authcInfo2 | ||
|
||
// Subject 3 - user is locked state | ||
authcInfo3 := authc.NewAuthenticationInfo() | ||
authcInfo3.Principals = append(authcInfo3.Principals, | ||
&authc.Principal{Value: "user2@example.com", IsPrimary: true, Realm: "inmemory"}) | ||
authcInfo3.Credential = []byte(`$2y$10$2A4GsJ6SmLAMvDe8XmTam.MSkKojdobBVJfIU7GiyoM.lWt.XV3H6`) // welcome123 | ||
authcInfo3.IsLocked = true | ||
fa.users["user2@example.com"] = *authcInfo3 | ||
|
||
// Subject 4 | ||
authcInfo4 := authc.NewAuthenticationInfo() | ||
authcInfo4.Principals = append(authcInfo4.Principals, | ||
&authc.Principal{Value: "user3@example.com", IsPrimary: true, Realm: "inmemory"}) | ||
authcInfo4.Credential = []byte(`$2y$10$2A4GsJ6SmLAMvDe8XmTam.MSkKojdobBVJfIU7GiyoM.lWt.XV3H6`) // welcome123 | ||
fa.users["user3@example.com"] = *authcInfo4 | ||
|
||
return nil | ||
} | ||
|
||
// GetAuthenticationInfo method is `authc.Authenticator` interface | ||
func (fa *FormAuthenticationProvider) GetAuthenticationInfo(authcToken *authc.AuthenticationToken) *authc.AuthenticationInfo { | ||
|
||
if ai, found := fa.users[authcToken.Identity]; found { | ||
return &ai | ||
} | ||
|
||
// No subject found, return nil | ||
return nil | ||
} | ||
|
||
func postAuthEvent(e *aah.Event) { | ||
ctx := e.Data.(*aah.Context) | ||
|
||
subjectName := ctx.Subject().PrimaryPrincipal().Value | ||
switch subjectName { | ||
case "user1@example.com": | ||
ctx.Session().Set("FirstName", "East") | ||
ctx.Session().Set("LastName", "Corner") | ||
case "user2@example.com": | ||
ctx.Session().Set("FirstName", "West") | ||
ctx.Session().Set("LastName", "Corner") | ||
case "user3@example.com": | ||
ctx.Session().Set("FirstName", "South") | ||
ctx.Session().Set("LastName", "Corner") | ||
case "admin@example.com": | ||
ctx.Session().Set("FirstName", "Admin") | ||
ctx.Session().Set("LastName", "Corner") | ||
} | ||
} | ||
|
||
func init() { | ||
aah.OnPostAuth(postAuthEvent) | ||
} |
67 changes: 67 additions & 0 deletions
67
form-based-auth/app/security/form_authorization_provider.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
package security | ||
|
||
import ( | ||
"aahframework.org/config.v0" | ||
"aahframework.org/security.v0/authc" | ||
"aahframework.org/security.v0/authz" | ||
) | ||
|
||
// FormAuthorizationProvider struct implements `authz.Authorizer` interface. | ||
type FormAuthorizationProvider struct { | ||
users map[string]authz.AuthorizationInfo | ||
} | ||
|
||
// Init method initializes the FormAuthoriationProvider, this method gets called | ||
// during server start up. | ||
func (fa *FormAuthorizationProvider) Init(cfg *config.Config) error { | ||
|
||
// NOTE: for demo purpose I'm creating set users in the map. | ||
// Typically you will be using Database, API calls, LDAP, etc to get the Authentication | ||
// Information. | ||
|
||
fa.users = make(map[string]authz.AuthorizationInfo) | ||
|
||
// Subject 1 | ||
authzInfo1 := authz.NewAuthorizationInfo() | ||
|
||
// Adding roles | ||
authzInfo1.AddRole("user", "manager") | ||
|
||
// Adding permissions | ||
// composed of domain is users, resource is manage, action is view | ||
// Learn about permission: http://docs.aahframework.org/security-permissions.html | ||
authzInfo1.AddPermissionString("users:manage:view") | ||
fa.users["user1@example.com"] = *authzInfo1 | ||
|
||
// Subject 2 | ||
authzInfo2 := authz.NewAuthorizationInfo() | ||
authzInfo2.AddRole("user", "administrator") | ||
// Learn about permission: http://docs.aahframework.org/security-permissions.html | ||
authzInfo2.AddPermissionString("users:*") | ||
fa.users["admin@example.com"] = *authzInfo2 | ||
|
||
// Subject 3 | ||
// We are not adding AuthorizationInfo since that user is locked. | ||
// Not required for demo. | ||
|
||
// Subject 4 | ||
authzInfo4 := authz.NewAuthorizationInfo() | ||
authzInfo4.AddRole("user") | ||
fa.users["user3@example.com"] = *authzInfo4 | ||
|
||
return nil | ||
} | ||
|
||
// GetAuthorizationInfo method is `authz.Authorizer` interface. | ||
// | ||
// GetAuthorizationInfo method gets called after authentication is successful | ||
// to get Subject's (aka User) access control information such as roles and permissions. | ||
func (fa *FormAuthorizationProvider) GetAuthorizationInfo(authcInfo *authc.AuthenticationInfo) *authz.AuthorizationInfo { | ||
|
||
if ai, found := fa.users[authcInfo.PrimaryPrincipal().Value]; found { | ||
return &ai | ||
} | ||
|
||
// No AuthorizationInfo for the subject, return nil | ||
return nil | ||
} |
Oops, something went wrong.