/// <summary> /// Tries to find a secret on the environment that can be used for authentication /// </summary> /// <param name="environment">The environment.</param> /// <returns> /// A parsed secret /// </returns> public async Task <ParsedSecret> ParseAsync(IDictionary <string, object> environment) { var context = new OwinContext(environment); if (!context.Request.Body.CanSeek) { var copy = new MemoryStream(); await context.Request.Body.CopyToAsync(copy); copy.Seek(0L, SeekOrigin.Begin); context.Request.Body = copy; } context.Request.Body.Seek(0L, SeekOrigin.Begin); var body = await context.Request.ReadFormAsync(); context.Request.Body.Seek(0L, SeekOrigin.Begin); var grantType = body.Get("grant_type"); if (String.IsNullOrEmpty(grantType)) { return(null); } var clientId = body.Get("client_id"); if (String.IsNullOrEmpty(clientId)) { return(null); } var clientSecret = body.Get("client_secret"); if (String.IsNullOrEmpty(clientSecret)) { return(null); } if (grantType == "client_credentials") { return(new ParsedSecret { Id = clientId, Credential = clientSecret.Sha256(), Type = "SharedSecret" }); } var certificate = Convert.FromBase64String(clientId); var signature = Convert.FromBase64String(clientSecret); var data = body.Get("access_token"); if (String.IsNullOrEmpty(data)) { return(null); } var accessToken = data; data = body.Get("nonce"); if (String.IsNullOrEmpty(data)) { return(null); } var nonce = Convert.FromBase64String(data); try { X509Certificate2 x509 = new X509Certificate2(certificate); // TBD - use a CertificateValidator to verify certificate. // check that the id matches the certificate. var applicationUri = Utils.GetApplicationUriFromCertificate(x509); // verify signature. var dataToVerify = Utils.Append(new UTF8Encoding(false).GetBytes(accessToken), nonce); if (!RsaUtils.RsaPkcs15Sha1_Verify(new ArraySegment <byte>(dataToVerify), signature, x509)) { return(null); } return(new ParsedSecret { Id = applicationUri, Credential = x509, Type = "ApplicationSignature" }); } catch (Exception) { return(null); } }