Use client usb signature in web application

moris27 51 Reputation points
2022-08-10T10:52:24.42+00:00

Hi
I have an working C# winforms app that uses a usb signature to get oAuth2 bearer token,uses Client ID(edClientID.Text),Client Secret(edSecret.Text),Callback URL(uCalback),asks for usb signature password then returns access_token and refresh_token

string code;  
readonly string URL_auth = "https://site1.com/authorize";  
readonly string URL_getToken = "https://site1.com/token";  
readonly char lfeed = (char)13;  
  
Token token = null;  
  
    try  
    {  
  
        string uCalback = HttpUtility.UrlEncode("https://www.site1.com");  
        string url = string.Format("{0}?response_type=code&client_id={1}&redirect_uri={2}", URL_auth, edClientID.Text, uCalback);  
  
        var handler = new WebRequestHandler  
        {  
            ClientCertificateOptions = ClientCertificateOption.Manual  
        };  
  
  
        var cert = GetUserCertificate();  
        handler.ClientCertificates.Add(cert);  
  
  
        handler.UseProxy = false;  
        HttpClient client = new HttpClient(handler);  
        string resultString;  
        HttpResponseMessage result;  
          
        try  
        {  
            result = client.GetAsync(url).GetAwaiter().GetResult();  
        }  
        ...  
  
        if (result.RequestMessage.RequestUri.Query.Contains("code="))  
        {  
            code = result.RequestMessage.RequestUri.Query.Replace("?code=", "");  
  
            var par = string.Format("grant_type=authorization_code&code={0}&client_id={1}&client_secret={2}&redirect_uri={3}",  
                code, edClientID.Text, edSecret.Text, uCalback);  
            try  
            {  
                result = client.PostAsync(URL_getToken, new StringContent(par)).GetAwaiter().GetResult();  
                resultString = result.Content.ReadAsStringAsync().GetAwaiter().GetResult();  
                if (resultString.Contains("access_token"))  
                {  
  
                    var js = new JavaScriptSerializer();  
                    token = js.Deserialize<Token>(resultString);  
                    ....  
  
                }  
            }  
           .....  
        }  
  
    }  
  
}  
  
  
  
  
 public class Token  
    {  
        public string access_token { get; set; }  
        public string refresh_token { get; set; }  
    }  
  
public static X509Certificate2 GetUserCertificate()  
{  
    X509Store store = new X509Store("MY", StoreLocation.CurrentUser);  
    store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);  
  
    X509Certificate2Collection collection = store.Certificates;  
    X509Certificate2Collection fcollection = collection.Find(X509FindType.FindByTimeValid, DateTime.Now, false);  
  
    X509Certificate2Collection HardCollection = new X509Certificate2Collection();  
    string sn = "";  
  
  
    foreach (var x5 in fcollection)  
    {  
            if (string.IsNullOrEmpty(sn) || (x5.SerialNumber == sn))  
                HardCollection.Add(x5);  
    }  
    if (HardCollection.Count > 1)  
    {  
        X509Certificate2Collection scollection = X509Certificate2UI.SelectFromCollection(HardCollection, "", "Select certificate", X509SelectionFlag.SingleSelection);  
        store.Close();  
        return scollection[0];  
    }  
    else  
    {  
        if (HardCollection.Count == 1)  
        {  
            store.Close();  
            return HardCollection[0];  
        }  
        else  
        {  
            store.Close();  
            return null;  
        }  
    }  
}  

  
  

I want to replace my winforms app with a web app(mywebapp.com),I've create a controller,but in this case,on the same computer If I go to mywebapp.com/cert/xxxxx/yyyy it doesn't ask for usb signature, If I put in browser the first GET request from the code https://site1/authorize?response_type=code&client_id=xxxxx&redirect_uri=https%3a%2f%2fwww.site1.com it asks for usb signature

[ApiController]  
[Route("[controller]")]  
public class CertController : ControllerBase  
{  
  
    [HttpGet]  
    [Route("/cert/{pClientID}/{pClientSecret}")]  
    public IActionResult GetCert(string pClientID, string pClientSecret)  
    {  
        string code, uCalback, resultString;  
        const char lfeed = (char)13;  
        HttpResponseMessage result;  
        
  
        try  
        {  
  
              uCalback = HttpUtility.UrlEncode("https://www.site1.com");  
              const string URL_auth = "https://site1.com/authorize";  
              const string URL_getToken = "https://site1.com/token";  
  
            var cert = GetUserCertificate();  
  
            var handler = new HttpClientHandler  
            {  
                ClientCertificateOptions = ClientCertificateOption.Manual,  
                UseProxy = false  
            };  
  
  
            handler.ClientCertificates.Add(cert);  
  
            HttpClient client = new HttpClient(handler);  
  
  
            try  
            {  
                result = client.GetAsync(string.Format("{0}?response_type=code&client_id={1}&redirect_uri={2}",  
                URL_auth, pClientID, uCalback)).GetAwaiter().GetResult();  
            }  
            catch (Exception ex)  
            {  
                throw new Exception(ex.Message);  
            }  
  
            if (result.RequestMessage.RequestUri.Query.Contains("code="))  
            {  
                code = result.RequestMessage.RequestUri.Query.Replace("?code=", "");  
  
                var par = string.Format("grant_type=authorization_code&code={0}&client_id={1}&client_secret={2}&redirect_uri={3}",  
                    code, pClientID, pClientSecret, uCalback);  
                try  
                {  
                    result = client.PostAsync(URL_getToken, new StringContent(par)).GetAwaiter().GetResult();  
                    resultString = result.Content.ReadAsStringAsync().GetAwaiter().GetResult();  
                    if (resultString.Contains("access_token"))  
                    {  
  
                        Token o = JsonConvert.DeserializeObject<Token>(resultString);  
  
                        return Ok($"access_token={o.access_token};refresh_token={o.refresh_token}");  
  
                    }  
                }  
               .....  
            }  
  
        }  
        catch (Exception ex)  
        {  
             ...  
        }  
  
    }  

    

thanks for any help

ASP.NET Core
ASP.NET Core
A set of technologies in the .NET Framework for building web applications and XML web services.
4,079 questions
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,098 questions
{count} votes

3 answers

Sort by: Most helpful
  1. moris27 51 Reputation points
    2022-08-11T10:39:35.457+00:00

    Hi
    I've added Authorize attribute,but not working

    I think web app controller reads certificates installed only on server machine(GetUserCertificate function) not on client.
    thanks

    0 comments No comments

  2. Bruce Barker 801 Reputation points
    2022-08-11T14:34:50.913+00:00

    As the cert access code is in the controller, it run on the computer hosting the website, and will access the hosting computers certificate store.

    0 comments No comments

  3. moris27 51 Reputation points
    2022-08-11T17:03:06.777+00:00

    in this case how can I get client certificate?
    thanks

    0 comments No comments