Skip to content

Digest

Digest authentication lets you authenticate a user without actually sending the password to the server. Instead the a request is made to the server, and a challenge issued back for credentials. The authentication is then done by comparing hashes generated by the client and server using the user's password as a secret key.

Setup

To setup and start using Digest authentication in Pode you use the New-PodeAuthScheme -Digest function, and then pipe this into the Add-PodeAuth function. The parameters supplied to the Add-PodeAuth function's ScriptBlock are the $username, and a HashTable containing the parameters from the Authorization header:

Start-PodeServer {
    New-PodeAuthScheme -Digest | Add-PodeAuth -Name 'Authenticate' -Sessionless -ScriptBlock {
        param($username, $params)

        # check if the user is valid

        return @{ User = $user; Password = $password }
    }
}

Unlike other forms of authentication where you only need return the User on success. Digest requires you to also return the Password of the user as a separate property. This password is what is used as the secret key to generate the client's response hash, and allows the server to re-generate the hash for validation. (Not returning the password will result in an HTTP 401 challenge response).

By default, Pode will check if the Request's header contains an Authorization key, and whether the value of that key starts with Digest tag. The New-PodeAuthScheme -Digest function can be supplied parameters to customise the tag using -HeaderTag. Pode will also gather the rest of the parameters in the header such as the Nonce, NonceCount, etc. An HTTP 401 challenge will be sent back if the Authorization header is invalid.

The HashTable of parameters sent to the Add-PodeAuth function's ScriptBlock are the following:

Parameter Description
cnonce A nonce value generated by the client
nc The count of time the client has used the server nonce
nonce A nonce value generated by the server
qop Fixed to 'auth'
realm The realm description from the server's HTTP 401 challenge
response The generated hash value of all these parameters from the client
uri The URI path that needs authentication
username The username of the user that needs authenticating

Middleware

Once configured you can start using Digest 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 Digest authentication to validate every request on every Route:

Start-PodeServer {
    Add-PodeAuthMiddleware -Name 'GlobalAuthValidation' -Authentication 'Authenticate'
}

Whereas the following example will use Digest authentication to only validate requests on specific a Route:

Start-PodeServer {
    Add-PodeRoute -Method Get -Path '/info' -Authentication 'Authenticate' -ScriptBlock {
        # logic
    }
}

Full Example

The following full example of Digest authentication will setup and configure authentication, validate that a user's username is valid, and then validate on a specific Route:

Start-PodeServer {
    Add-PodeEndpoint -Address * -Port 8080 -Protocol Http

    # setup digest authentication to validate a user
    New-PodeAuthScheme -Digest | Add-PodeAuth -Name 'Authenticate' -Sessionless -ScriptBlock {
        param($username, $params)

        # here you'd check a real user storage, this is just for example
        if ($username -eq 'morty') {
            return @{
                User = @{
                    'ID' ='M0R7Y302'
                    'Name' = 'Morty';
                    'Type' = 'Human';
                }
                Password = 'pickle'
            }
        }

        # authentication failed
        return $null
    }

    # check the request on this route against the authentication
    Add-PodeRoute -Method Get -Path '/cpu' -Authentication 'Authenticate' -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 }
    }
}