Skip to content

Commit

Permalink
#992: tweak to the functions, it's now Add-PodeAuthAccess with a re-u…
Browse files Browse the repository at this point in the history
…sable Test-PodeAuthUserAccess. Also added IsAuthorised property to WebEvent.Auth
  • Loading branch information
Badgerati committed Aug 14, 2023
1 parent b576a64 commit 02080bd
Show file tree
Hide file tree
Showing 8 changed files with 162 additions and 83 deletions.
9 changes: 7 additions & 2 deletions examples/web-auth-basic-access.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ Start-PodeServer -Threads 2 {
Add-PodeEndpoint -Address * -Port 8085 -Protocol Http

# setup RBAC
$rbac = New-PodeAuthAccess -Type Role
Add-PodeAuthAccess -Type Role -Name 'TestRbac'

# setup basic auth (base64> username:password in header)
New-PodeAuthScheme -Basic -Realm 'Pode Example Page' | Add-PodeAuth -Name 'Validate' -Access $rbac -Sessionless -ScriptBlock {
New-PodeAuthScheme -Basic -Realm 'Pode Example Page' | Add-PodeAuth -Name 'Validate' -Access 'TestRbac' -Sessionless -ScriptBlock {
param($username, $password)

# here you'd check a real user storage, this is just for example
Expand All @@ -47,6 +47,11 @@ Start-PodeServer -Threads 2 {
return @{ Message = 'Invalid details supplied' }
}

# Endware to output user auth state
Add-PodeEndware -ScriptBlock {
$WebEvent.Auth | Out-Default
}

# POST request to get list of users - there's no Roles, so any auth'd user can access
Add-PodeRoute -Method Post -Path '/users-all' -Authentication 'Validate' -ScriptBlock {
Write-PodeJsonResponse -Value @{
Expand Down
6 changes: 5 additions & 1 deletion src/Pode.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,11 @@
'Use-PodeAuth',
'ConvertFrom-PodeOIDCDiscovery',
'Test-PodeAuthUser',
'New-PodeAuthAccess',
'Add-PodeAuthAccess',
'Add-PodeAuthCustomAccess',
'Get-PodeAuthAccess',
'Test-PodeAuthAccess',
'Test-PodeAuthUserAccess',

# logging
'New-PodeLoggingMethod',
Expand Down
70 changes: 17 additions & 53 deletions src/Private/Authentication.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -1236,6 +1236,8 @@ function Get-PodeAuthMiddlewareScript
$WebEvent.Auth = @{}
$WebEvent.Auth.User = $result.User
$WebEvent.Auth.IsAuthenticated = $true
$WebEvent.Auth.Access = $null
$WebEvent.Auth.IsAuthorised = $true
$WebEvent.Auth.Store = !$sessionless

# continue, but check access
Expand Down Expand Up @@ -1319,7 +1321,7 @@ function Set-PodeAuthStatus
$Success,

[Parameter()]
[hashtable[]]
[string[]]
$Access,

[switch]
Expand Down Expand Up @@ -1389,7 +1391,7 @@ function Set-PodeAuthStatus
}

foreach ($acc in $Access) {
if (!(Test-PodeAuthAccess -Access $acc)) {
if (!(Test-PodeAuthRouteAccess -Name $acc)) {
return (Set-PodeAuthStatus `
-StatusCode 403 `
-Description $Description `
Expand Down Expand Up @@ -1901,7 +1903,7 @@ function Find-PodeAuth
$Name
)

return $PodeContext.Server.Authentications[$Name]
return $PodeContext.Server.Authentications.Methods[$Name]
}

function Test-PodeAuth
Expand All @@ -1913,7 +1915,7 @@ function Test-PodeAuth
$Name
)

return $PodeContext.Server.Authentications.ContainsKey($Name)
return $PodeContext.Server.Authentications.Methods.ContainsKey($Name)
}

function Import-PodeAuthADModule
Expand Down Expand Up @@ -1954,65 +1956,27 @@ function Get-PodeAuthADProvider
return 'DirectoryServices'
}

function Test-PodeAuthAccess
function Test-PodeAuthRouteAccess
{
param(
[Parameter(Mandatory=$true)]
[hashtable]
$Access
[string]
$Name
)

# get the access method
$access = $PodeContext.Server.Authentications.Access[$Name]

# get route access values - if none then skip
$routeAccess = $WebEvent.Route.Access[$Access.Type]
if ($Access.IsCustom) {
$routeAccess = $routeAccess[$Access.Name]
$routeAccess = $WebEvent.Route.Access[$access.Type]
if ($access.IsCustom) {
$routeAccess = $routeAccess[$access.Name]
}

if (($null -eq $routeAccess) -or ($routeAccess.Length -eq 0)) {
return $true
}

# if there's no scriptblock, try the Path fallback
if ($null -eq $Access.Scriptblock) {
$userAccess = $WebEvent.Auth.User
foreach ($atom in $Access.Path.Split('.')) {
$userAccess = $userAccess.($atom)
}
}

# otherwise, invoke scriptblock
else {
$_args = @($WebEvent.Auth.User) + @($Access.Arguments)
$_args = @(Get-PodeScriptblockArguments -ArgumentList $_args -UsingVariables $Access.Scriptblock.UsingVariables)
$userAccess = Invoke-PodeScriptBlock -ScriptBlock $Access.Scriptblock.Script -Arguments $_args -Return -Splat
}

# check for custom validator, or use default match logic
if ($null -ne $Access.Validator) {
$_args = @(,$userAccess) + @(,$routeAccess) + @($Access.Arguments)
$_args = @(Get-PodeScriptblockArguments -ArgumentList $_args -UsingVariables $Access.Validator.UsingVariables)
return (Invoke-PodeScriptBlock -ScriptBlock $Access.Validator.Script -Arguments $_args -Return -Splat)
}

# one or all match?
else {
if ($Access.Match -ieq 'one') {
foreach ($item in $userAccess) {
if ($item -iin $routeAccess) {
return $true
}
}

return $false
}
else {
foreach ($item in $routeAccess) {
if ($item -inotin $userAccess) {
return $false
}
}

return $true
}
}
# now test the user's access against the route's access
return (Test-PodeAuthUserAccess -Name $Name -Value $routeAccess)
}
7 changes: 5 additions & 2 deletions src/Private/Context.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -351,8 +351,11 @@ function New-PodeContext
}
}

# authnetication methods
$ctx.Server.Authentications = @{}
# authentication methods and access
$ctx.Server.Authentications = @{
Methods = @{}
Access = @{}
}

# create new cancellation tokens
$ctx.Tokens = @{
Expand Down
4 changes: 2 additions & 2 deletions src/Private/OpenApi.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -267,12 +267,12 @@ function Get-PodeOpenApiDefinitionInternal
$def['components'] = $PodeContext.Server.OpenAPI.components

# auth/security components
if ($PodeContext.Server.Authentications.Count -gt 0) {
if ($PodeContext.Server.Authentications.Methods.Count -gt 0) {
if ($null -eq $def.components.securitySchemes) {
$def.components.securitySchemes = @{}
}

foreach ($authName in $PodeContext.Server.Authentications.Keys) {
foreach ($authName in $PodeContext.Server.Authentications.Methods.Keys) {
$authType = (Find-PodeAuth -Name $authName).Scheme
$_authName = ($authName -replace '\s+', '')

Expand Down
3 changes: 2 additions & 1 deletion src/Private/Server.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,8 @@ function Restart-PodeInternalServer
$PodeContext.Server.Sessions.Clear()

# clear up authentication methods
$PodeContext.Server.Authentications.Clear()
$PodeContext.Server.Authentications.Methods.Clear()
$PodeContext.Server.Authentications.Access.Clear()

# clear up shared state
$PodeContext.Server.State.Clear()
Expand Down
Loading

0 comments on commit 02080bd

Please sign in to comment.