Is there any JSON Web Token (JWT) example in C#?

前端 未结 9 2405
悲哀的现实
悲哀的现实 2020-11-28 01:10

I feel like I\'m taking crazy pills here. Usually there\'s always a million library and samples floating around the web for any given task. I\'m trying to implement authenti

9条回答
  •  一生所求
    2020-11-28 01:56

    Here is another REST-only working example for Google Service Accounts accessing G Suite Users and Groups, authenticating through JWT. This was only possible through reflection of Google libraries, since Google documentation of these APIs are beyond terrible. Anyone used to code in MS technologies will have a hard time figuring out how everything goes together in Google services.

    $iss = "@.iam.gserviceaccount.com"; # The email address of the service account.
    $sub = "impersonate.user@mydomain.com"; # The user to impersonate (required).
    $scope = "https://www.googleapis.com/auth/admin.directory.user.readonly https://www.googleapis.com/auth/admin.directory.group.readonly";
    $certPath = "D:\temp\mycertificate.p12";
    $grantType = "urn:ietf:params:oauth:grant-type:jwt-bearer";
    
    # Auxiliary functions
    function UrlSafeEncode([String] $Data) {
        return $Data.Replace("=", [String]::Empty).Replace("+", "-").Replace("/", "_");
    }
    
    function UrlSafeBase64Encode ([String] $Data) {
        return (UrlSafeEncode -Data ([Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($Data))));
    }
    
    function KeyFromCertificate([System.Security.Cryptography.X509Certificates.X509Certificate2] $Certificate) {
        $privateKeyBlob = $Certificate.PrivateKey.ExportCspBlob($true);
        $key = New-Object System.Security.Cryptography.RSACryptoServiceProvider;
        $key.ImportCspBlob($privateKeyBlob);
        return $key;
    }
    
    function CreateSignature ([Byte[]] $Data, [System.Security.Cryptography.X509Certificates.X509Certificate2] $Certificate) {
        $sha256 = [System.Security.Cryptography.SHA256]::Create();
        $key = (KeyFromCertificate $Certificate);
        $assertionHash = $sha256.ComputeHash($Data);
        $sig = [Convert]::ToBase64String($key.SignHash($assertionHash, "2.16.840.1.101.3.4.2.1"));
        $sha256.Dispose();
        return $sig;
    }
    
    function CreateAssertionFromPayload ([String] $Payload, [System.Security.Cryptography.X509Certificates.X509Certificate2] $Certificate) {
        $header = @"
    {"alg":"RS256","typ":"JWT"}
    "@;
        $assertion = New-Object System.Text.StringBuilder;
    
        $assertion.Append((UrlSafeBase64Encode $header)).Append(".").Append((UrlSafeBase64Encode $Payload)) | Out-Null;
        $signature = (CreateSignature -Data ([System.Text.Encoding]::ASCII.GetBytes($assertion.ToString())) -Certificate $Certificate);
        $assertion.Append(".").Append((UrlSafeEncode $signature)) | Out-Null;
        return $assertion.ToString();
    }
    
    $baseDateTime = New-Object DateTime(1970, 1, 1, 0, 0, 0, [DateTimeKind]::Utc);
    $timeInSeconds = [Math]::Truncate([DateTime]::UtcNow.Subtract($baseDateTime).TotalSeconds);
    
    $jwtClaimSet = @"
    {"scope":"$scope","email_verified":false,"iss":"$iss","sub":"$sub","aud":"https://oauth2.googleapis.com/token","exp":$($timeInSeconds + 3600),"iat":$timeInSeconds}
    "@;
    
    
    $cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($certPath, "notasecret", [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::Exportable);
    $jwt = CreateAssertionFromPayload -Payload $jwtClaimSet -Certificate $cert;
    
    
    # Retrieve the authorization token.
    $authRes = Invoke-WebRequest -Uri "https://oauth2.googleapis.com/token" -Method Post -ContentType "application/x-www-form-urlencoded" -UseBasicParsing -Body @"
    assertion=$jwt&grant_type=$([Uri]::EscapeDataString($grantType))
    "@;
    $authInfo = ConvertFrom-Json -InputObject $authRes.Content;
    
    $resUsers = Invoke-WebRequest -Uri "https://www.googleapis.com/admin/directory/v1/users?domain=" -Method Get -Headers @{
        "Authorization" = "$($authInfo.token_type) $($authInfo.access_token)"
    }
    
    $users = ConvertFrom-Json -InputObject $resUsers.Content;
    
    $users.users | ft primaryEmail, isAdmin, suspended;
    

提交回复
热议问题