Search code examples
f#pass-by-referencec#-to-f#byref

c# to f# when 3rd party lib wants a byref as an out parameter


I’m trying to convert this method into F#

private static bool VerifySignedJwt(ECDsa eCDsa, string token) {
    var tokenHandler = new JwtSecurityTokenHandler();
    var claimsPrincipal = tokenHandler.ValidateToken(token, new TokenValidationParameters {
        ValidIssuer = "me",
        ValidAudience = "you",
        IssuerSigningKey = new ECDsaSecurityKey(eCDsa)
    }, out var parsedToken);
    return claimsPrincipal.Identity.IsAuthenticated;
}

I’m translating this great piece of work by Scott Brady in order to create and validate JWT tokens for a web app, the creation part went without a hitch. On with the Validation part and the reference to a byref required in the JwtSecurityTokenHandler.ValidateToken method has stumped me. https://www.scottbrady91.com/C-Sharp/JWT-Signing-using-ECDSA-in-dotnet-Core

If I follow the Microsoft docs below; I get an error saying a “type instantiation involves a byref type. This is not permitted by the rules of Common IL.” When trying to declare a byref as:

let _h (x: byref<'T>) = ()

https://learn.microsoft.com/en-us/dotnet/fsharp/language-reference/byrefs I have read the Microsoft docs on byrefs but am left wondering if this relates to .Net core or F#4.5 or does dotnet core supersede all features including byrefs in F#4.5? Either way I can’t seem to instantiate a SecurityToken at all, the "out var parsedToken" is a SecurityToken type, let alone a byref one to use as an output to this 3rd party library, or I can’t seem to declare a byref SecurityToken directly in the call to JwtSecurityTokenHandler.ValidateToken.

If I use the advice posted in this SO post Using c# delegates with f# functions

let function_1 (x:double) (y:double byref) = 
    y <- 6.0

I get the same error “type instantiation involves a byref type. This is not permitted by the rules of Common IL.”

I have used Byrefs before in F# but these were simple integer types and worked without issue. My project is .Net core 2.1

Any help appreciated.


Solution

  • Since the out parameter in the ValidateToken() call is the last one, you can simply omit it, and treat it as a second return value:

    let claimsPrincipal, parsedToken = tokenHandler.ValidateToken (token, tvp)
    

    (Here tvp would be your TokenValidationParameters instance.)

    See also https://learn.microsoft.com/en-us/dotnet/fsharp/language-reference/parameters-and-arguments#passing-by-reference for more information.

    EDIT: Since you don't seem to be using the second return value, I figure your function could look as follows:

    let verifySignedJwt ecdsa token =
        let tokenHandler = JwtSecurityTokenHandler ()
        let tvp = TokenValidationParameters (ValidIssuer = "me",
                                             ValidAudience = "you",
                                             IssuerSigningKey = ECDsaSecurityKey ecdsa)
        let claimsPrincipal, _ = tokenHandler.ValidateToken (token, tvp)
        claimsPrincipal.Identity.IsAuthenticated