1

Please see codes below. I got the following error on line

var result = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();

Error: The input is not a valid Base-64 string as it contains a non-base 64 character, more than two padding characters, or an illegal character among the padding characters.

Not sure what i did wrong. Please help!

using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using System.IdentityModel.Tokens;
using System.Security.Cryptography;
using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using System.Net;
using Newtonsoft.Json;
using System.Net.Http;
using System.Net.Http.Headers;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            string privateKeyFilePath = "C:\\Users\\privateKey.txt";
            string privateKey;
            string clientId = "myclientid";
            string serraviewUri = "https://instance.serraview.com";

            try
            {
                privateKey = File.ReadAllText(privateKeyFilePath);
            }
            catch (Exception ex)
            {
                return;
            }

            // Convert PEM to RSA using the BouncyCastle library.
            var rsa = new RSACryptoServiceProvider();
            RSAParameters rsaParameters;

            using (var privateKeyReader = new StringReader(privateKey))
            {
                var pemReader = new PemReader(privateKeyReader);
                var keyPair = (AsymmetricCipherKeyPair)pemReader.ReadObject();
                var privKey = (RsaPrivateCrtKeyParameters)keyPair.Private;
                rsaParameters = DotNetUtilities.ToRSAParameters(privKey);
            }
            rsa.ImportParameters(rsaParameters);

            // The only signing algorithm supported by the Serraview Authorization Server is RSA using SHA-256 hashing algorithm.
            var signingKey = new RsaSecurityKey(rsa);
            var signingCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.RsaSha256Signature, SecurityAlgorithms.Sha256Digest);

            // Get audience for the JWT. This will be the url for the authorization server we request an access token from.
            Uri uri;
            Uri.TryCreate(serraviewUri, UriKind.Absolute, out uri);

            Uri audience;
            if (!Uri.TryCreate(uri, "/oauth2/token", out audience))
            {
                return;
            }

            // Build JWT
            var jwt = new JwtSecurityToken(
                clientId,
                audience.ToString(),
                null, 
                DateTime.UtcNow /*not before*/,
                DateTime.UtcNow.AddMinutes(5) /*expires*/,
                signingCredentials);

            // Serialize our jwt object to an actual JWT string
            var jwtString = new JwtSecurityTokenHandler().WriteToken(jwt);

            // Request an access token
            // Serraview servers require TLS1.2
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;

            string accessToken;
            using (var client = new System.Net.Http.HttpClient())
            {
                client.BaseAddress = uri;

                var content = new System.Net.Http.FormUrlEncodedContent(
                new[]
                {
                    new KeyValuePair<string, string>("grant_type","urn:ietf:params:oauth:grant-type:jwt-bearer"),
                    new KeyValuePair<string, string>("assertion", jwtString)
                });

                var response = client.PostAsync("/oauth2/token", content).GetAwaiter().GetResult();
                var result = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
                dynamic parsedJson = JsonConvert.DeserializeObject(result);
                accessToken = parsedJson["access_token"];
            }
            
            Console.WriteLine(accessToken);
            Console.Read();  
        }

    }
}

I tried webclient and the same issue. The response returns 200 but output "Error: the input...." after encoding it to a string.

enter image description here

enter image description here

enter image description here

The following is part of the SerraView API doc. enter image description here

I have tested with Postman and it threw "unsupported grant_type" enter image description here

Matteo Umili
  • 3,412
  • 1
  • 19
  • 31
Alex W.
  • 546
  • 1
  • 7
  • 22
  • Step into it if you can to see what is returned from the API request. Or use something like fiddler to log the traffic. You can also try system.net.webrequest or WebClient. – John Jul 28 '20 at 03:23
  • Thank John for your response. I tried WebClient and same result. To clarify, no exceptions were thrown. It just output "error: the input is not a valid..." Please see the original post. – Alex W. Jul 28 '20 at 22:34
  • could you try using await in the more traditional style var response = await client.PostAsync("/oauth2/token", content); you will also need to change Main from void to async Task – Twisted Jul 28 '20 at 22:49
  • I tried using await (please see above) - the same issue. @Twisted – Alex W. Jul 29 '20 at 02:11
  • @AlexW. when you used await where you able to get a response back? - does the error move to the point at which you try to read from the response? eg is it an issue with the response returned from the token endpoint and not your code. – Twisted Jul 29 '20 at 08:48
  • @AlexW from your screen shot it does indeed look like an issue with the response. I would debug that and particularly the contents of the result string - can you use the debugger to paste it into a text file and check the encoding? Seems likely to be an issue with the service you are calling. – Twisted Jul 29 '20 at 10:15
  • Thanks @Twisted. Exceptions were throw from response.content. the message is "This stream does not support seek operations." Please see above screen shot. – Alex W. Jul 29 '20 at 17:19
  • hey guys also check this https://stackoverflow.com/questions/23259173/unexpected-character-encountered-while-parsing-value – Nadeem Taj Jul 30 '20 at 04:35
  • @AlexW. It sounds to me like you are not getting text as a response from that token endpoint. I suggest further debugging, such as trying to call the token endpoint with a tool like Postman. Also check that you are sending the correct parameters - I've never seen an "assertion" parameter or a jwt-bearer grant type. Also sometimes you need to pass headers to specify that you want a json response or a certain version of the endpoint. It's all guesses, I know, but it may help. – Twisted Jul 30 '20 at 11:16
  • @Twisted I have added screenshot of the part of the API doc in the original post. You can see the endpoint and required parameters which I am not sure what i did wrong. Also I have tested with Posman and it threw "unsupported grant_type". – Alex W. Jul 30 '20 at 14:52
  • 2
    your postman request is not proper, remove "grant_type" and "assertion" from params tab and add them under body -> x-www-form-urlencoded section. – Durga Prasad Aug 01 '20 at 18:58
  • JWT tokens are made of multiple blocks. Is assertion meant to be base64 encoded? – ProgrammingLlama Aug 03 '20 at 14:04

0 Answers0