Need help with server to server OAuth authentication using C#

Looking for sample C# code to do server to server OAuth authentication for a C# console application. I currently have C# code that does JWT authentication. Looking to change this since JWT authentication will be discontinued. If anybody can provide some samples, that will be really helpful.

This is my code -


Console.WriteLine(“Starting…”);

var accountId = “xxxxxxxxxxxxxxx”;
var clientID = “xxxxxxxxxxxx”;
var clientSecret = “xxxxxxxxxxxxxxx”;

string restcli = “https://zoom.us/oauth/token?grant_type=account_credentials&accountId=” + accountId;

var client = new RestClient(restcli);
//client.Timeout = -1;

var request = new RestRequest(restcli);
request.AddHeader(“Authorization”, “Basic <base64encoded_”+ clientID + “_”+clientSecret+ “>”);

RestResponse response = client.Execute(request);

Console.WriteLine(response.Content);

And I am getting a “Request failed with status code MethodNotAllowed” in the response.

After additional research, I modified my code to this -


Console.WriteLine(“Starting…”);

var accountId = “xxxxxxxxxxxxxxxx”;
var clientID = “xxxxxxxxxxxxxxxxxxxxxx”;
var clientSecret = “xxxxxxxxxxxxxxxxxxxxxxxxxxxxx”;

string restcli = “https://zoom.us/oauth/token?grant_type=account_credentials&accountId=” + accountId;

RestClient client = new RestClient(restcli);

var request = new RestRequest(restcli);
request.Timeout = -1;

string clientID_clientSecret = clientID + “:” + clientSecret;

var plaintextbytes = System.Text.Encoding.UTF8.GetBytes(clientID_clientSecret);
string base64Value = System.Convert.ToBase64String(plaintextbytes);

request.AddHeader(“Authorization”, "Basic "+base64Value);

RestResponse response = client.Execute(request);

Console.WriteLine(response.Content);

And I am still getting a “Request failed with status code MethodNotAllowed” - Some sample codes of C# Server-to-Server OAuth authentication would really be helpful.

Looking at our implementation (which uses a different technology stack):

  • The contents of your query string should be included in the request body instead (still formatted as a query string).
  • The parameter name should be spelled account_id instead of using camel case.
  • Declare your content type in a header such as: Content-Type: application/x-www-form-urlencoded; charset=utf-8
  • Use the POST method (not GET).

I’m not sure what framework you’re using to send these requests (I’m most familiar with HttpWebRequest in the .NET Framework world), so I can’t recommend which properties and methods you should use.

Hi Christopher, thanks for responding. As mentioned, I am using C# developing on Visual Studio 2022. Do you by any chance have a sample HttpWebRequest code in C# that I can try for the authentication? Any help would be much appreciated.

Thanks,
Ravi.

This sample is for a different organization’s API (not for Zoom), but uses a pretty similar workflow that you can use as a starting point.

using System.IO;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using System.Web.Script.Serialization;

		static internal async Task<string> ReadResponseTextForResponseAsync(WebResponse authorizationResponse)
		{
			string authorizationResponseText;
			using (Stream authorizationResponseStream = authorizationResponse.GetResponseStream())
			{
				UTF8Encoding textEncoderWithoutBOM = new UTF8Encoding(false);
				long responseLengthLong = authorizationResponse.ContentLength;
				if (0 <= responseLengthLong)
				{
					int responseRemainder = (int)responseLengthLong;
					byte[] responseBytes = new byte[responseRemainder];
					int responseIndex = 0;
					int responseBytesRead;
					do
					{
						responseBytesRead = await authorizationResponseStream.ReadAsync(responseBytes, responseIndex, responseRemainder).ConfigureAwait(false);
						responseIndex += responseBytesRead;
						responseRemainder -= responseBytesRead;
					} while (responseBytesRead != 0);
					/* UNDONE:  observe response charset. */
					authorizationResponseText = textEncoderWithoutBOM.GetString(responseBytes);
				}
				else
				{
					int responseRemainder = 4096;
					byte[] responseBytes = new byte[responseRemainder];
					int responseIndex = 0;
					int responseBytesRead;
					do
					{
						responseBytesRead = await authorizationResponseStream.ReadAsync(responseBytes, responseIndex, responseRemainder).ConfigureAwait(false);
						responseIndex += responseBytesRead;
						responseRemainder -= responseBytesRead;
						if(responseIndex == responseBytes.Length)
						{
							Array.Resize<byte>(ref responseBytes, responseIndex + 4096);
							responseRemainder += 4096;
						}
						if(responseRemainder < 1)
						{
							break;
						}
					} while (responseBytesRead != 0);
					Array.Resize<byte>(ref responseBytes, responseIndex);
					/* UNDONE:  observe response charset. */
					authorizationResponseText = textEncoderWithoutBOM.GetString(responseBytes);
				}
			}
			return authorizationResponseText;
		}

		static internal async Task<string> GetAccessTokenResponseTextAsync()
		{
			string authorizationResponseText;
			HttpWebRequest authorizationRequest = (HttpWebRequest)WebRequest.Create(ContosoHandler.FabrikamAuthURL);
			authorizationRequest.Accept = "application/json";
			authorizationRequest.ContentType = "application/x-www-form-urlencoded; charset=utf-8";
			authorizationRequest.Method = "POST";
			string authorizationRequestBody = "client_id=" + HttpUtility.UrlEncode(ContosoHandler.FabrikamClientID) + "&client_secret=" + HttpUtility.UrlEncode(ContosoHandler.FabrikamSecretKey) + "&grant_type=client_credentials&scope=openid";
			UTF8Encoding textEncoderWithoutBOM = new UTF8Encoding(false);
			byte[] authorizationRequestBodyBytes = textEncoderWithoutBOM.GetBytes(authorizationRequestBody);
			authorizationRequest.ContentLength = authorizationRequestBodyBytes.Length;
			using (Stream authorizationRequestStream = await authorizationRequest.GetRequestStreamAsync().ConfigureAwait(false))
			{
				await authorizationRequestStream.WriteAsync(authorizationRequestBodyBytes, 0, authorizationRequestBodyBytes.Length).ConfigureAwait(false);
				authorizationRequestStream.Close();
				WebResponse authorizationResponse;
				try
				{
					authorizationResponse = await authorizationRequest.GetResponseAsync().ConfigureAwait(false);
				}
				catch (WebException problem)
				{
					authorizationResponse = problem.Response;
					throw;
				}

				using (authorizationResponse)
				{
					authorizationResponseText = await ContosoHandler.ReadResponseTextForResponseAsync(authorizationResponse).ConfigureAwait(false);
					authorizationResponse.Close();
				}
			}

			return authorizationResponseText;
		}

		static internal string GetAccessTokenFromAuthorizationResponse(string authorizationResponseText, out int accessTokenLifetimeSeconds)
		{
			JavaScriptSerializer serializer = new JavaScriptSerializer();
			Dictionary<string, object> authorizationResponseObject = serializer.Deserialize<Dictionary<string, object>>(authorizationResponseText);
			string accessToken = (string)authorizationResponseObject["access_token"];
			accessTokenLifetimeSeconds = (int)authorizationResponseObject["expires_in"];
			return accessToken;
		}
1 Like

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.