Skip to content

Commit

Permalink
form-based auth tutorial application added
Browse files Browse the repository at this point in the history
  • Loading branch information
jeevatkm committed Jul 24, 2017
1 parent 1046850 commit 91ed453
Show file tree
Hide file tree
Showing 25 changed files with 1,460 additions and 0 deletions.
30 changes: 30 additions & 0 deletions form-based-auth/.gitignore
@@ -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
54 changes: 54 additions & 0 deletions form-based-auth/aah.project
@@ -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"]
}
21 changes: 21 additions & 0 deletions form-based-auth/app/controllers/admin/dashboard.go
@@ -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()
}
63 changes: 63 additions & 0 deletions form-based-auth/app/controllers/app.go
@@ -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)
}
6 changes: 6 additions & 0 deletions form-based-auth/app/models/greet.go
@@ -0,0 +1,6 @@
package models

// Greet holds the greeting message.
type Greet struct {
Message string `json:"message"`
}
90 changes: 90 additions & 0 deletions form-based-auth/app/security/form_authentication_provider.go
@@ -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 form-based-auth/app/security/form_authorization_provider.go
@@ -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
}

0 comments on commit 91ed453

Please sign in to comment.