New-UDAuthenticationMethod return HTTP status code 500 for ErrorRecord that has been caught

Hi everyone,

Given the following simplified authentication handler for /api/login in a UDRestApi:

$LoginAuth = New-UDAuthenticationMethod -Endpoint {
    Param([PSCredential]$Credential)

    try {
        $account = Get-ADUser $Credential.UserName -Credential $Credential
    } catch {
        New-UDAuthenticationResult -ErrorMessage "Invalid credentials"
    }
    New-UDAuthenticationResult -Success -UserName $account.SamAccountName -Role Admin
}

The result of an authentication failure is always a 500 errror. Not the expected JSON payload with success: false and errorMessage. But if the authentication is successful (i.e. if Get-ADUser does not throw an exception) authentication will succeed.

Trying to simplify this even more, I cannot reproduce throwing a simple exception like this:

try {
    throw "TEST"
} catch {
    New-UDAuthenticationResult -ErrorMessage "Invalid credentials"
}

Using this authentication code, I will always get a proper JSON response, not a 500 error.

I figured out that a 500 error code seem to be returned if a terminating ErrorRecord is created, for example like this:

try {
    Write-Error "BOOM" -ErrorAction Stop
} catch {
    New-UDAuthenticationResult -ErrorMessage "Invalid credentials"
}

And if instead we have a non-terminating ErrorRecord created during the execution like this:

Write-Error "BOOM"
New-UDAuthenticationResult -ErrorMessage "Invalid credentials"

The resulting API response will be 200 with a body of:

{
    "error": "BOOM"
}

I am not sure what to make of this. I have yet to test if this applies to all endpoints or if this is specific of the authentication method, but it is causing me quite a headache already.

I need to authenticate users against ADand get their roles from AD as weel before I give them a token for the REST API access. I need to be able to handle errors without the API framework taking over like the boss of me and assuming the worst. If this applies to all endpoints as well, there better be a workaround otherwise it will effectively make my project a no go.

Any way to work around this? Did I miss something important in the documentation?

Thanks!

Marco

Seems like a bug to me. I’ll look into it.

OK, thanks. Let me know if you prefer I open a ticket on Github for this. I wasn’t sure if I should get the discussion started here first or if I shouldreport such things in Github instead.

Cheers

Opening a GitHub issue would be great. It’s fine to throw something up on the forums first to feel it out but to best track, it should be on GitHub. Thanks!

I see you opened #1199 for this already but I will open an issue next time. Thanks!

Feel free to reach out if you need further input from me.

Also, there is not edit button on my original post anymore, so just FYI, my example is missing a return here:

$LoginAuth = New-UDAuthenticationMethod -Endpoint {
Param([PSCredential]$Credential)

try {
    $account = Get-ADUser $Credential.UserName -Credential $Credential
} catch {
    New-UDAuthenticationResult -ErrorMessage "Invalid credentials"
    return # ---> MISSING IN ORIGINAL POST
}
New-UDAuthenticationResult -Success -UserName $account.SamAccountName -Role Admin
}

That was only missing in the post itself. The issue described is unchanged.

This will be fixed in the next version. I think you can work around this in the current version by changing it to this.

$LoginAuth = New-UDAuthenticationMethod -Endpoint {
Param([PSCredential]$Credential)

$account = Get-ADUser $Credential.UserName -Credential $Credential -ErrorAction SilentlyContinue
if ($null -eq $account) 
{
    New-UDAuthenticationResult -ErrorMessage "Invalid credentials"
    return # ---> MISSING IN ORIGINAL POST
}

New-UDAuthenticationResult -Success -UserName $account.SamAccountName -Role Admin
}

UD was checking the error stream to see if there were errors. If there were it was just erroring out. Now it checks to see if there were errors in and error stream AND no authentication result was being returned.

Hi Adam!

Great news! Unfortunately the workaround does not work because lots of AD cmdlets don’t fully honor the ErrorAction flag for some reason (.NET implementation?). e.g.:

PS> Get-ADUser $bad.UserName -Credential $bad -ErrorAction SilentlyContinue
Get-ADUser : The server has rejected the client credentials.
At line:1 char:1
+ Get-ADUser $bad.UserName -Credential $bad -ErrorAction SilentlyContin ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : SecurityError: (sfsdsfd:ADUser) [Get-ADUser], AuthenticationException
    + FullyQualifiedErrorId : The server has rejected the client credentials.,Microsoft.ActiveDirectory.Management.Commands.GetADUser

But I’m busy enough to wait the next release. No worry there.

Thanks!

Thanks for the feedback! Thanks!