Skip to content

Commit

Permalink
#1179: fix for missing merged auth docs, and add a quicker default se…
Browse files Browse the repository at this point in the history
…lector for merging All auths
  • Loading branch information
Badgerati committed Apr 3, 2024
1 parent 120efdd commit 0eccb86
Show file tree
Hide file tree
Showing 6 changed files with 178 additions and 72 deletions.
132 changes: 99 additions & 33 deletions docs/Tutorials/Authentication/Overview.md

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions examples/tcp-server-auth.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Start-PodeServer -Threads 2 {
New-PodeLoggingMethod -Terminal | Enable-PodeErrorLogging

# create a role access method get retrieves roles from a database
Add-PodeAccess -Name 'RoleExample' -Type Role -ScriptBlock {
New-PodeAccessScheme -Type Role | Add-PodeAccess -Name 'RoleExample' -ScriptBlock {
param($username)
if ($username -ieq 'morty') {
return @('Developer')
Expand All @@ -26,12 +26,12 @@ Start-PodeServer -Threads 2 {
# setup a Verb that only allows Developers
Add-PodeVerb -Verb 'EXAMPLE :username' -ScriptBlock {
if (!(Test-PodeAccess -Name 'RoleExample' -Destination 'Developer' -ArgumentList $TcpEvent.Parameters.username)) {
Write-PodeTcpClient -Message "Forbidden Access"
Write-PodeTcpClient -Message 'Forbidden Access'
'Forbidden!' | Out-Default
return
}

Write-PodeTcpClient -Message "Hello, there!"
Write-PodeTcpClient -Message 'Hello, there!'
'Hello!' | Out-Default
}
}
18 changes: 6 additions & 12 deletions examples/web-auth-basic-access.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,8 @@ Start-PodeServer -Threads 2 {
Add-PodeEndpoint -Address * -Port 8085 -Protocol Http

# setup RBAC
# Add-PodeAccess -Type Role -Name 'TestRbac'
# Add-PodeAccess -Type Group -Name 'TestGbac'
New-PodeAccessScheme -Type Role | Add-PodeAccess -Name 'TestRbac'
New-PodeAccessScheme -Type Group | Add-PodeAccess -Name 'TestGbac'
# Add-PodeAccess -Type Custom -Name 'TestRbac' -Path 'CustomAccess' -Validator {
# param($userRoles, $customValues)
# return $userRoles.Example -iin $customValues.Example
# }

Merge-PodeAccess -Name 'TestMergedAll' -Access 'TestRbac', 'TestGbac' -Valid All
Merge-PodeAccess -Name 'TestMergedOne' -Access 'TestRbac', 'TestGbac' -Valid One
Expand All @@ -46,12 +40,12 @@ Start-PodeServer -Threads 2 {
if ($username -eq 'morty' -and $password -eq 'pickle') {
return @{
User = @{
ID ='M0R7Y302'
Name = 'Morty'
Type = 'Human'
Username = 'm.orty'
Roles = @('Developer')
Groups = @('Software', 'Admins')
ID = 'M0R7Y302'
Name = 'Morty'
Type = 'Human'
Username = 'm.orty'
Roles = @('Developer')
Groups = @('Software', 'Admins')
CustomAccess = @{ Example = 'test-val-1' }
}
}
Expand Down
47 changes: 32 additions & 15 deletions examples/web-auth-merged.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -21,24 +21,25 @@ Start-PodeServer -Threads 2 {
New-PodeLoggingMethod -Terminal -Batch 10 -BatchTimeout 10 | Enable-PodeRequestLogging

# setup access
Add-PodeAccess -Type Role -Name 'Rbac'
Add-PodeAccess -Type Group -Name 'Gbac'
New-PodeAccessScheme -Type Role | Add-PodeAccess -Name 'Rbac'
New-PodeAccessScheme -Type Group | Add-PodeAccess -Name 'Gbac'

# setup a merged access
Merge-PodeAccess -Name 'MergedAccess' -Access 'Rbac', 'Gbac' -Valid All

# setup apikey auth
New-PodeAuthScheme -ApiKey -Location Header | Add-PodeAuth -Name 'ApiKey' -Access 'Gbac' -Sessionless -ScriptBlock {
New-PodeAuthScheme -ApiKey -Location Header | Add-PodeAuth -Name 'ApiKey' -Sessionless -ScriptBlock {
param($key)

# here you'd check a real user storage, this is just for example
if ($key -ieq 'test-api-key') {
return @{
User = @{
ID ='M0R7Y302'
Name = 'Morty'
Type = 'Human'
Groups = @('Software')
ID = 'M0R7Y302'
Name = 'Morty'
Type = 'Human'
Roles = @('Developer')
Groups = @('Platform')
}
}
}
Expand All @@ -47,19 +48,19 @@ Start-PodeServer -Threads 2 {
}

# setup basic auth (base64> username:password in header)
New-PodeAuthScheme -Basic | Add-PodeAuth -Name 'Basic' -Access 'MergedAccess' -Sessionless -ScriptBlock {
New-PodeAuthScheme -Basic | Add-PodeAuth -Name 'Basic' -Sessionless -ScriptBlock {
param($username, $password)

# here you'd check a real user storage, this is just for example
if ($username -eq 'morty' -and $password -eq 'pickle') {
return @{
User = @{
Username = 'morty'
ID ='M0R7Y302'
Name = 'Morty'
Type = 'Human'
Roles = @('Developer')
Groups = @('Software')
ID = 'M0R7Y302'
Name = 'Morty'
Type = 'Human'
Roles = @('Developer')
Groups = @('Software')
}
}
}
Expand All @@ -68,10 +69,26 @@ Start-PodeServer -Threads 2 {
}

# merge the auths together
Merge-PodeAuth -Name 'MergedAuth' -Authentication 'ApiKey', 'Basic' -Valid All
Merge-PodeAuth -Name 'MergedAuth' -Authentication 'ApiKey', 'Basic' -Valid All -ScriptBlock {
param($results)

$apiUser = $results['ApiKey'].User
$basicUser = $results['Basic'].User

return @{
User = @{
Username = $basicUser.Username
ID = $apiUser.ID
Name = $apiUser.Name
Type = $apiUser.Type
Roles = @($apiUser.Roles + $basicUser.Roles) | Sort-Object -Unique
Groups = @($apiUser.Groups + $basicUser.Groups) | Sort-Object -Unique
}
}
}

# GET request to get list of users (since there's no session, authentication will always happen)
Add-PodeRoute -Method Get -Path '/users' -Authentication 'MergedAuth' -Role Developer -Group Software -ScriptBlock {
Add-PodeRoute -Method Get -Path '/users' -Authentication 'MergedAuth' -Access 'MergedAccess' -Role Developer -Group Software -ScriptBlock {
Write-PodeJsonResponse -Value @{
Users = $WebEvent.Auth.User
}
Expand Down
16 changes: 12 additions & 4 deletions src/Private/Authentication.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -828,10 +828,13 @@ function Invoke-PodeAuthInbuiltScriptBlock {
$ScriptBlock,

[Parameter()]
$UsingVariables
$UsingVariables,

[switch]
$NoSplat
)

return (Invoke-PodeScriptBlock -ScriptBlock $ScriptBlock -Arguments $User -UsingVariables $UsingVariables -Return -Splat)
return (Invoke-PodeScriptBlock -ScriptBlock $ScriptBlock -Arguments $User -UsingVariables $UsingVariables -Return -Splat:(!$NoSplat))
}

function Get-PodeAuthWindowsLocalMethod {
Expand Down Expand Up @@ -1120,8 +1123,13 @@ function Invoke-PodeAuthValidation {

# if the last auth succeeded, and we need all to pass, merge users/headers and return result
if ($result.Success -and !$auth.PassOne) {
# invoke scriptblock
$result = Invoke-PodeAuthInbuiltScriptBlock -User $results -ScriptBlock $auth.ScriptBlock.Script -UsingVariables $auth.ScriptBlock.UsingVariables
# invoke scriptblock, or use result of merge default
if ($null -ne $auth.ScriptBlock.Script) {
$result = Invoke-PodeAuthInbuiltScriptBlock -User $results -ScriptBlock $auth.ScriptBlock.Script -UsingVariables $auth.ScriptBlock.UsingVariables -NoSplat
}
else {
$result = $results[$auth.MergeDefault]
}

# reset default properties and return
$result.Success = $true
Expand Down
31 changes: 26 additions & 5 deletions src/Public/Authentication.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -804,12 +804,15 @@ Multiple Autentication method Names to be merged.
How many of the Authentication methods are required to be valid, One or All. (Default: One)
.PARAMETER ScriptBlock
This is mandatory when Valid is All. A scriptblock to merge the mutliple users/headers returned by valid authentications into 1 user/header objects.
This is mandatory, and only used, when $Valid=All. A scriptblock to merge the mutliple users/headers returned by valid authentications into 1 user/header objects.
This scriptblock will receive a hashtable of all result objects returned from Authentication methods. The key for the hashtable will be the authentication names that passed.
.PARAMETER Default
The Default Authentication method to use as a fallback for Failure URLs and other settings.
.PARAMETER MergeDefault
The Default Authentication method's User details result object to use, when $Valid=All.
.PARAMETER FailureUrl
The URL to redirect to when authentication fails.
This will be used as fallback for the merged Authentication methods if not set on them.
Expand All @@ -831,13 +834,16 @@ If supplied, successful authentication from a login page will redirect back to t
This will be used as fallback for the merged Authentication methods if not set on them.
.EXAMPLE
Merge-PodeAuth -Name MergedAuth -Authentication ApiTokenAuth, BasicAuth -Valid All
Merge-PodeAuth -Name MergedAuth -Authentication ApiTokenAuth, BasicAuth -Valid All -ScriptBlock { ... }
.EXAMPLE
Merge-PodeAuth -Name MergedAuth -Authentication ApiTokenAuth, BasicAuth -Valid All -MergeDefault BasicAuth
.EXAMPLE
Merge-PodeAuth -Name MergedAuth -Authentication ApiTokenAuth, BasicAuth -FailureUrl 'http://localhost:8080/login'
#>
function Merge-PodeAuth {
[CmdletBinding()]
[CmdletBinding(DefaultParameterSetName = 'ScriptBlock')]
param(
[Parameter(Mandatory = $true)]
[string]
Expand All @@ -853,14 +859,18 @@ function Merge-PodeAuth {
[string]
$Valid = 'One',

[Parameter()]
[Parameter(ParameterSetName = 'ScriptBlock')]
[scriptblock]
$ScriptBlock,

[Parameter()]
[string]
$Default,

[Parameter(ParameterSetName = 'MergeDefault')]
[string]
$MergeDefault,

[Parameter()]
[string]
$FailureUrl,
Expand Down Expand Up @@ -892,6 +902,11 @@ function Merge-PodeAuth {
}
}

# ensure the merge default is in the auth list
if (![string]::IsNullOrEmpty($MergeDefault) -and ($MergeDefault -inotin @($Authentication))) {
throw "the MergeDefault Authentication '$($MergeDefault)' is not in the Authentication list supplied"
}

# ensure the default is in the auth list
if (![string]::IsNullOrEmpty($Default) -and ($Default -inotin @($Authentication))) {
throw "the Default Authentication '$($Default)' is not in the Authentication list supplied"
Expand Down Expand Up @@ -936,13 +951,18 @@ function Merge-PodeAuth {
}

# deal with using vars in scriptblock
if ($Valid -ieq 'all') {
if (($Valid -ieq 'all') -and [string]::IsNullOrEmpty($MergeDefault)) {
if ($null -eq $ScriptBlock) {
throw 'A Scriptblock for merging multiple authenticated users into 1 object is required When Valid is All'
}

$ScriptBlock, $usingVars = Convert-PodeScopedVariables -ScriptBlock $ScriptBlock -PSSession $PSCmdlet.SessionState
}
else {
if ($null -ne $ScriptBlock) {
Write-Warning -Message 'The Scriptblock for merged authentications, when Valid=One, will be ignored'
}
}

# set parent auth
foreach ($authName in $Authentication) {
Expand All @@ -959,6 +979,7 @@ function Merge-PodeAuth {
UsingVariables = $usingVars
}
Default = $Default
MergeDefault = $MergeDefault
Sessionless = $Sessionless.IsPresent
Failure = @{
Url = $FailureUrl
Expand Down

0 comments on commit 0eccb86

Please sign in to comment.