none
CredentialPicker.PickAsync - How to Validate Certificate Authentication RRS feed

  • Question

  • Hello All,

    When using the CredentialPicker.PickAsync(System.String, System.String) function, there is no way to validate certain user credentials because the information returned is encrypted and unverifiable. 

    In the case of the following code sample, I specify the results of an authentication using an arbitrary user certificate.  As you can see, the information returned does not specify the certificate information used, nor can we clearly discern how to validate the user’s credentials (AKA validating the signature). 

    NOTES:
    Built on UWP 8.1 Desktop (NOT PHONE)

    var newCred = await CredentialPicker.PickAsync("My-Target", "This is some message!");
    
    var bytes = newCred.Credential.ToArray();
    var msg = string.Format("Credential(Length = {1}): {0}\r\n", Convert.ToBase64String(bytes), bytes.Length);
    msg += string.Format("CredentialUsername: {0}\r\n", newCred.CredentialUserName);
    msg += string.Format("CredentialPassword: {0}\r\n", newCred.CredentialPassword
    	.Replace("\a", "\\a")
    	.Replace("\0", "\\0")
    	.Replace("\t", "\\t")
    	.Replace("\b", "\\b")
    	.Replace("\f", "\\f")
    	.Replace("\n", "\\n")
    	.Replace("\r", "\\r")
    );
    
    /* msg = 
    Credential(Length = 266): AQIAADAAAAACAQAAMAAAADwAAAAAAAAAAAAAAGwAAACOAAAAAAABAAAAAAAAAAAAQABAAEIASAAxADMASQBIAHoAZwA5AHAAbQBkAHEAQwBxAGQANgBlAGQAQQB5AFAAVABVAFgAdwBJAEsAHACOAC/Dvyj2EDhHmNEawGHfcWocAAAAcgAAAEAAQABEAAcACAAMAAoADQBnAEEAQQBBAEEAQQB4ADYAcABhAEIAQQBBAEEAQQBBAHcAdgBSAEEAUQBMAHIAcwBEAFYAaABSAGYAdABJAEIALQBmADEAdgBkAEsASwAjAFIASQByAGoAZgB6AGcALQBQAAAAAAAAAAAAAAAAAAAAAAA=
    CredentialUsername: @@BH13IHzg9pmdqCqd6edAyPTUXwIK
    CredentialPassword: @@D\a\b\f\n\rgAAAAAx6paBAAAAAwvRAQLrsDVhRftIB-f1vdKK#RIrjfzg-P
    
    */
    


    - Rashad Rivera www.omegusprime.com

    Friday, October 7, 2016 10:37 PM

All replies

  • All,

    Because I know someone is going to ask:

    1. No.  The "Windows-universal-sample-master" does not cover this topic.  In addition, it does not even show how to programmatically use the credentials returned by the call; which I feel is a deficiency
    2. No.  The 266 bytes returned does NOT represent the certificates specified by the user. 

      Certificate are generally 500 bytes and greater in size.  In the case of the certificate I specified, it is 789 bytes in length and because the integrity of the certificate would be violated if altered, we know that this call could not be returning the certificate specified by the user.
    3. No.  The MSDN documentation does not cover this scenario.

    Thanks in advance. 


    - Rashad Rivera www.omegusprime.com


    • Edited by Rashad Rivera Friday, October 7, 2016 10:57 PM Further clarifying.
    Friday, October 7, 2016 10:55 PM
  • Hi Rashad Rivera,

    Welcome to the Developing Universal Windows apps forum!

    Please read the sticky posts, especially the Guide to posting: subject line tags and Known Issues for Windows 10 SDK and Tools 

    >>” here is no way to validate certain user credentials because the information returned is encrypted and unverifiable.”

    I have tested the windows 8.1 official code sample and UWP code sample:

    UWP Credential picker sample

    windows 8.1 CredentialPicker sample

    I can get the user name of the unpacked credential, domain name etc. They’re not encrypted. It's different from yours. And The password will always be returned encrypted by calling this APIs. All supported networking APIs will decrypt this automatically. So I think you don’t need to care about this point.

    Best Regards,

    Xavier Eoro


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.



    Tuesday, October 11, 2016 9:30 AM
    Moderator
  • Rashad,

    Did you ever figure out how to make sense of the CredentialPickerResults object returned from the CredentialPicker when selecting a smart card certificate? I'm faced with the same issue.

    Friday, April 5, 2019 10:20 PM
  • Hello All,

    The suggestion was not an answer to the issue.  I eventually solved this by using one of a back channel technique in where we contact a web app that requires client certicate authentication and feed that cert back to your app.  The best being the HttpClient, but you have to grant your app more permissions (which may not be something your user is willing to accept).  Honestly, this is all from memory folks. 

    - Option A(Not my first choice): Use a WebBrowser control that loads a custom web-page.  The web page is configured for ClientCertificate authentication.  You can use an ASP.Net Web Form or an MVC app.  In either case, when the user specified a good certificate (meaning trusted by the web server), your web code can safely gain a copy of their public certificate using the Request.ClientCertificate property to test the presence of a certificate and its validity.  The Request.ClientCertificate.Certificate property gives you a byte array of the cert.  With this information, you can return the certificate to your W8.1 code via JSon, Text or what every format you need.  Since your W8.1 app contacted the server via HTTPS, you can trust its response.

    - Option B: Use the same web app that requires ClientCertificate authentication, but use the System.Net.Http.HttpClient class with the config that automatically prompts the user for certificates.  (see HttpClient with Client certificate and accepting all server certificates)

    // Web API Code Sample
    public class DefaultController : Controller {
    
    	// GET: Default
    	public ActionResult Index() {
    
    		if (this.Request.ClientCertificate.IsPresent && this.Request.ClientCertificate.IsValid) {
    
    			var certBytes = Convert.ToBase64String(this.Request.ClientCertificate.Certificate);
    			return this.Json(new { status = "OK", certbytes = certBytes }, JsonRequestBehavior.AllowGet);
    		} else
    			return this.Json(new { status = "Not OK", certbytes = string.Empty }, JsonRequestBehavior.AllowGet);
    	}
    }
    
    
    // UWP Code Sample (as close to WP8.1 as I can get)
    async void MainPage_Loaded(object sender, Windows.UI.Xaml.RoutedEventArgs e) {
    
    	var clientcert = new System.Net.Http.HttpClientHandler {
    		ClientCertificateOptions = System.Net.Http.ClientCertificateOption.Automatic
    	};
    
    	HttpClient client = new System.Net.Http.HttpClient(clientcert);
    	var jsonText = await client.GetStringAsync(new Uri("https://localhost:12345/ClientCertWebApp/default/index"));
    	this.idResponseText.Text = jsonText;
    }


    Some things to keep in mind, Windows 8 Store Apps is not supported and thus, it is difficult to find online references.  Again, I'm trying my best to remember how I solved this problem.  I would use Windows 10 UWP these days which has more features like access to the user's My certificate store where you can determine which certs you trust.  You can also generate certificates and store them in a virtual certificate store that is tied to your app.

    Other References

    https://github.com/dotnet/corefx/issues/24211


    - Rashad Rivera [omegusprime.com]


    • Edited by Rashad Rivera Wednesday, April 17, 2019 3:07 AM Code sample in wrong place
    Wednesday, April 17, 2019 3:06 AM