Skip to content

Commit

Permalink
feat: Add session claims helper methods to check roles and permissions
Browse files Browse the repository at this point in the history
  • Loading branch information
mzhong9723 committed Jan 10, 2024
1 parent fede4e5 commit 7c37e14
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 12 deletions.
38 changes: 38 additions & 0 deletions clerk/session_claims.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package clerk

import (
"encoding/json"

"github.com/go-jose/go-jose/v3/jwt"
)

type SessionClaims struct {
jwt.Claims
SessionID string `json:"sid"`
AuthorizedParty string `json:"azp"`
ActiveOrganizationID string `json:"org_id"`
ActiveOrganizationSlug string `json:"org_slug"`
ActiveOrganizationRole string `json:"org_role"`
ActiveOrganizationPermissions []string `json:"org_permissions"`
Actor json.RawMessage `json:"act,omitempty"`
}

// HasPermission checks if the user has the specific permission
// in their session claims.
func (s *SessionClaims) HasPermission(permission string) bool {
for _, sessPermission := range s.ActiveOrganizationPermissions {
if sessPermission == permission {
return true
}
}
return false
}

// HasRole checks if the user has the specific role
// in their session claims.
// Performing role checks is not considered a best-practice and
// developers should avoid it as much as possible.
// Usually, complex role checks can be refactored with a single permission check.
func (s *SessionClaims) HasRole(role string) bool {
return s.ActiveOrganizationRole == role
}
27 changes: 27 additions & 0 deletions clerk/session_claims_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package clerk

import (
"testing"

"github.com/stretchr/testify/assert"
)

func TestSessionClaims_HasPermissiont(t *testing.T) {
// user has permission
hasPermission := dummySessionClaims.HasPermission("org:billing:manage")
assert.True(t, hasPermission)

// user does not have permission
hasPermission = dummySessionClaims.HasPermission("org:billing:create")
assert.False(t, hasPermission)
}

func TestSessionClaims_HasRole(t *testing.T) {
// user has role
hasRole := dummySessionClaims.HasRole("org_role")
assert.True(t, hasRole)

// user does not have role
hasRole = dummySessionClaims.HasRole("org_role_nonexistent")
assert.False(t, hasRole)
}
12 changes: 0 additions & 12 deletions clerk/tokens.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package clerk

import (
"encoding/json"
"fmt"
"time"

Expand All @@ -16,17 +15,6 @@ type TokenClaims struct {
Extra map[string]interface{}
}

type SessionClaims struct {
jwt.Claims
SessionID string `json:"sid"`
AuthorizedParty string `json:"azp"`
ActiveOrganizationID string `json:"org_id"`
ActiveOrganizationSlug string `json:"org_slug"`
ActiveOrganizationRole string `json:"org_role"`
ActiveOrganizationPermissions []string `json:"org_permissions"`
Actor json.RawMessage `json:"act,omitempty"`
}

// DecodeToken decodes a jwt token without verifying it.
func (c *client) DecodeToken(token string) (*TokenClaims, error) {
parsedToken, err := jwt.ParseSigned(token)
Expand Down

0 comments on commit 7c37e14

Please sign in to comment.