Custom
Custom authentication works much like the inbuilt schemes (Basic/Form/etc), but allows you to specify your own parsing logic, as well as any custom options that might be required.
Setup and Parsing
To setup and start using Custom authentication in Pode you use the New-PodeAuthScheme -Custom
function, and then pipe this into the Add-PodeAuth
function.
Let's say we wanted something similar to Form
Authentication, but it requires a third piece of information: ClientName
. To setup Custom authentication for this method, you'll need to specify the parsing logic within the -ScriptBlock
of the New-PodeAuthScheme
function.
The -ScriptBlock
on New-PodeAuthScheme
will have access to the current web event variable: $WebEvent
. In this script you can parse the Request payload/headers for any credential information that needs validating. Once sourced the data returned from the script should be an array
, which will then splatted onto the -ScriptBlock
from your Add-PodeAuth
function:
Start-PodeServer {
# define a new custom authentication scheme
$custom_scheme = New-PodeAuthScheme -Custom -ScriptBlock {
param($opts)
# get client/user/password field names
$clientField = (Protect-PodeValue -Value $opts.ClientField -Default 'client')
$userField = (Protect-PodeValue -Value $opts.UsernameField -Default 'username')
$passField = (Protect-PodeValue -Value $opts.PasswordField -Default 'password')
# get the client/user/password from the request's post data
$client = $WebEvent.Data.$clientField
$username = $WebEvent.Data.$userField
$password = $WebEvent.Data.$passField
# return the data in a array, which will be passed to the validator script
return @($client, $username, $password)
}
# now, add a new custom authentication validator using the scheme you created above
$custom_scheme | Add-PodeAuth -Name 'Login' -ScriptBlock {
param($client, $username, $password)
# check if the client is valid in some database
# return a user object (return $null if validation failed)
return @{ User = $user }
}
}
Note
The $opts
parameter in the New-PodeAuthScheme
ScriptBlock come from the -ArgumentList
HashTable.
Post Validation
The typical setup of authentication is that you create some scheme to parse the request (New-PodeAuthScheme
), and then you pipe this into a validator to validate the parsed user's credentials (Add-PodeAuth
).
There is however also an optional -PostValidator
ScriptBlock that can be passed to your Custom authentication scheme on the New-PodeAuthScheme
function. This -PostValidator
script runs after normal user validation, and also has access to the current web event. The original splatted array returned from the New-PodeAuthScheme
ScriptBlock, the result HashTable from the user validator from Add-PodeAuth
, and the -ArgumentList
HashTable from New-PodeAuthScheme
are supplied as parameters. You can use this script to re-generate any hashes for further validation, but if successful you must return the User object again (ie: re-return the last parameter which is the original validation result).
For example, if you have a post validator script for the above Client Custom authentication, then it would be supplied the following parameters:
- ClientName
- Username
- Password
- Validation Result
- Scheme ArgumentsList
For example:
Start-PodeServer {
# define a new custom authentication scheme
$custom_scheme = New-PodeAuthScheme -Custom -ScriptBlock {
param($opts)
# get client/user/password field names
$clientField = (Protect-PodeValue -Value $opts.ClientField -Default 'client')
$userField = (Protect-PodeValue -Value $opts.UsernameField -Default 'username')
$passField = (Protect-PodeValue -Value $opts.PasswordField -Default 'password')
# get the client/user/password from the request's post data
$client = $WebEvent.Data.$clientField
$username = $WebEvent.Data.$userField
$password = $WebEvent.Data.$passField
# return the data in a array, which will be passed to the validator script
return @($client, $username, $password)
} `
-PostValidator {
param($client, $username, $password, $result, $opts)
# run any extra post-validation logic
# the result is the object returned from the below scriptblock
return $result
}
# now, add a new custom authentication method using the scheme you created above
$custom_scheme | Add-PodeAuth -Name 'Login' -ScriptBlock {
param($client, $username, $password)
# check if the client is valid in some database
# return a user object (return $null if validation failed)
return @{ User = $user }
}
}
Middleware
Once configured you can start using the Custom authentication to validate incoming Requests. You can either configure the validation to happen on every Route as global Middleware, or as custom Route Middleware.
The following will use Custom authentication to validate every request on every Route:
Start-PodeServer {
Add-PodeAuthMiddleware -Name 'GlobalAuthValidation' -Authentication 'Login'
}
Whereas the following example will use Custom authentication to only validate requests on specific a Route:
Start-PodeServer {
Add-PodeRoute -Method Get -Path '/info' -Authentication 'Login' -ScriptBlock {
# logic
}
}
Full Example
The following full example of Custom authentication will setup and configure authentication, validate that a users client/username/password is valid, and then validate on a specific route
:
Start-PodeServer {
Add-PodeEndpoint -Address * -Port 8080 -Protocol Http
# define a new custom authentication scheme
$custom_scheme = New-PodeAuthScheme -Custom -ScriptBlock {
param($opts)
# get client/user/pass field names to get from payload
$clientField = (Protect-PodeValue -Value $opts.ClientField -Default 'client')
$userField = (Protect-PodeValue -Value $opts.UsernameField -Default 'username')
$passField = (Protect-PodeValue -Value $opts.PasswordField -Default 'password')
# get the client/user/pass from the post data
$client = $WebEvent.Data.$clientField
$username = $WebEvent.Data.$userField
$password = $WebEvent.Data.$passField
# return the data, to be passed to the validator script
return @($client, $username, $password)
}
# now, add a new custom authentication method
$custom_scheme | Add-PodeAuth -Name 'Login' -Sessionless -ScriptBlock {
param($client, $username, $password)
# check if the client is valid
# return a user object (return $null if validation failed)
return @{ User = $user }
}
# check the request on this route against the authentication
Add-PodeRoute -Method Get -Path '/cpu' -Authentication 'Login' -ScriptBlock {
Write-PodeJsonResponse -Value @{ 'cpu' = 82 }
}
# this route will not be validated against the authentication
Add-PodeRoute -Method Get -Path '/memory' -ScriptBlock {
Write-PodeJsonResponse -Value @{ 'memory' = 14 }
}
}
Below is an example HTML page that would POST the client/username/password to the server above:
<form action="/login" method="post">
<div>
<label>Client:</label>
<input type="text" name="client"/>
</div>
<div>
<label>Username:</label>
<input type="text" name="username"/>
</div>
<div>
<label>Password:</label>
<input type="password" name="password"/>
</div>
<div>
<input type="submit" value="Login"/>
</div>
</form>