1

Is there any netstandard 2.0 sample for authorization code flow with Identitity4 and OidcClient? like SystemBrowser that is only in .net core

Mustafa
  • 77
  • 8

1 Answers1

0

Here my first try using only .net stanard 2.0 classes:

using IdentityModel.OidcClient.Browser;
using System;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;

namespace IVT.OAuth.Client
{
    public class SystemBrowser : IBrowser
    {
        private readonly string sRedirect;

        public SystemBrowser(string sRedirect)
        {
            this.sRedirect = sRedirect;
        }

        public async Task<BrowserResult> InvokeAsync(BrowserOptions options, CancellationToken cancellationToken)
        {
            using (var oListener = new HttpListener())
            {
                using (var process = OpenBrowser(options.StartUrl))
                {
                    BrowserResult result = null;
                    oListener.Prefixes.Add(sRedirect);
                    try
                    {
                        var CodeResult = await ReceiveCode(oListener);
                        if (String.IsNullOrWhiteSpace(CodeResult.Item1))
                        {
                            result = new BrowserResult { ResultType = BrowserResultType.UnknownError, Error = "Empty response." };
                        }
                        else
                        {

                            SendResponse(CodeResult.Item2.Response, "<h1>You can now return to the application.</h1>");
                            Thread.Sleep(1000);

                            result = new BrowserResult { Response = CodeResult.Item1, ResultType = BrowserResultType.Success };
                        }
                    }
                    catch (TaskCanceledException ex)
                    {
                        result = new BrowserResult { ResultType = BrowserResultType.Timeout, Error = ex.Message };
                    }
                    catch (Exception ex)
                    {
                        result = new BrowserResult { ResultType = BrowserResultType.UnknownError, Error = ex.Message };
                    }

                    //process.CloseMainWindow();                    
                    //process.Close();

                    return result;
                }

            }
        }

        private async Task<Tuple<string, HttpListenerContext>> ReceiveCode(HttpListener oListener)
        {
            string sCode = string.Empty;
            HttpListenerContext oContext = null;

            if (!oListener.IsListening)
                oListener.Start();

            try
            {
                oContext = await oListener.GetContextAsync();
                if (oContext.Request.QueryString.AllKeys.Contains("error"))
                {
                    var sErrorMessage = oContext.Request.QueryString["error"] + Environment.NewLine +
                                    oContext.Request.QueryString["error_description"];
                }
                else
                {
                    sCode = oContext.Request.Url.Query;
                }
            }
            catch (Exception oException)
            {
            }

            return new Tuple<string, HttpListenerContext>(sCode, oContext);
        }

        private void SendResponse(HttpListenerResponse response, string responseString)
        {        
            byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseString);
            // Get a response stream and write the response to it.
            response.ContentLength64 = buffer.Length;
            System.IO.Stream output = response.OutputStream;
            output.Write(buffer, 0, buffer.Length);
            response.StatusCode = 200;
            response.ContentType = "text/html";
            // You must close the output stream.
            output.Close();
        }

        public static Process OpenBrowser(string url)
        {
            try
            {
                return Process.Start(new ProcessStartInfo(url));
            }
            catch
            {
                // hack because of this: https://github.com/dotnet/corefx/issues/10361
                if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
                {
                    url = url.Replace("&", "^&");
                    return Process.Start(new ProcessStartInfo("cmd", $"/c start {url}") { CreateNoWindow = true });
                }
                else
                {
                    throw;
                }
            }
        }
    }
}
Mustafa
  • 77
  • 8