コード例 #1
0
 string Thumbprint(string kty, string e, string n)
 {
     return(Base64Url.Encode(Util.Sha256Hash(Encoding.ASCII.GetBytes(
                                                 $"{{\"e\":\"{e}\",\"kty\":\"{kty}\",\"n\":\"{n}\"}}"))));
 }
コード例 #2
0
 public void SetSignature(byte[] signature)
 {
     Signature = Base64Url.Encode(signature);
 }
コード例 #3
0
        /// <summary>
        /// Creates the JWK document.
        /// </summary>
        public virtual async Task <IEnumerable <Models.JsonWebKey> > CreateJwkDocumentAsync()
        {
            var webKeys = new List <Models.JsonWebKey>();

            foreach (var key in await Keys.GetValidationKeysAsync())
            {
                if (key.Key is X509SecurityKey x509Key)
                {
                    var cert64     = Convert.ToBase64String(x509Key.Certificate.RawData);
                    var thumbprint = Base64Url.Encode(x509Key.Certificate.GetCertHash());

                    if (x509Key.PublicKey is RSA rsa)
                    {
                        var parameters = rsa.ExportParameters(false);
                        var exponent   = Base64Url.Encode(parameters.Exponent);
                        var modulus    = Base64Url.Encode(parameters.Modulus);

                        var rsaJsonWebKey = new Models.JsonWebKey
                        {
                            kty = "RSA",
                            use = "sig",
                            kid = x509Key.KeyId,
                            x5t = thumbprint,
                            e   = exponent,
                            n   = modulus,
                            x5c = new[] { cert64 },
                            alg = key.SigningAlgorithm
                        };
                        webKeys.Add(rsaJsonWebKey);
                    }
                    else if (x509Key.PublicKey is ECDsa ecdsa)
                    {
                        var parameters = ecdsa.ExportParameters(false);
                        var x          = Base64Url.Encode(parameters.Q.X);
                        var y          = Base64Url.Encode(parameters.Q.Y);

                        var ecdsaJsonWebKey = new Models.JsonWebKey
                        {
                            kty = "EC",
                            use = "sig",
                            kid = x509Key.KeyId,
                            x5t = thumbprint,
                            x   = x,
                            y   = y,
                            crv = CryptoHelper.GetCrvValueFromCurve(parameters.Curve),
                            x5c = new[] { cert64 },
                            alg = key.SigningAlgorithm
                        };
                        webKeys.Add(ecdsaJsonWebKey);
                    }
                    else
                    {
                        throw new InvalidOperationException($"key type: {x509Key.PublicKey.GetType().Name} not supported.");
                    }
                }
                else if (key.Key is RsaSecurityKey rsaKey)
                {
                    var parameters = rsaKey.Rsa?.ExportParameters(false) ?? rsaKey.Parameters;
                    var exponent   = Base64Url.Encode(parameters.Exponent);
                    var modulus    = Base64Url.Encode(parameters.Modulus);

                    var webKey = new Models.JsonWebKey
                    {
                        kty = "RSA",
                        use = "sig",
                        kid = rsaKey.KeyId,
                        e   = exponent,
                        n   = modulus,
                        alg = key.SigningAlgorithm
                    };

                    webKeys.Add(webKey);
                }
                else if (key.Key is ECDsaSecurityKey ecdsaKey)
                {
                    var parameters = ecdsaKey.ECDsa.ExportParameters(false);
                    var x          = Base64Url.Encode(parameters.Q.X);
                    var y          = Base64Url.Encode(parameters.Q.Y);

                    var ecdsaJsonWebKey = new Models.JsonWebKey
                    {
                        kty = "EC",
                        use = "sig",
                        kid = ecdsaKey.KeyId,
                        x   = x,
                        y   = y,
                        crv = CryptoHelper.GetCrvValueFromCurve(parameters.Curve),
                        alg = key.SigningAlgorithm
                    };
                    webKeys.Add(ecdsaJsonWebKey);
                }
                else if (key.Key is JsonWebKey jsonWebKey)
                {
                    var webKey = new Models.JsonWebKey
                    {
                        kty = jsonWebKey.Kty,
                        use = jsonWebKey.Use ?? "sig",
                        kid = jsonWebKey.Kid,
                        x5t = jsonWebKey.X5t,
                        e   = jsonWebKey.E,
                        n   = jsonWebKey.N,
                        x5c = jsonWebKey.X5c?.Count == 0 ? null : jsonWebKey.X5c.ToArray(),
                        alg = jsonWebKey.Alg,
                        crv = jsonWebKey.Crv,
                        x   = jsonWebKey.X,
                        y   = jsonWebKey.Y
                    };

                    webKeys.Add(webKey);
                }
            }

            return(webKeys);
        }
コード例 #4
0
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddHttpClient();

            services.AddMvc(options =>
            {
                var global = new AuthorizationPolicyBuilder()
                             .RequireAuthenticatedUser()
                             .Build();

                options.Filters.Add(new AuthorizeFilter(global));
            }).SetCompatibilityVersion(Microsoft.AspNetCore.Mvc.CompatibilityVersion.Version_2_1);

            services.AddAuthentication(options =>
            {
                options.DefaultScheme          = "cookies";
                options.DefaultChallengeScheme = "oidc";
            })
            .AddCookie("cookies", options =>
            {
                options.AccessDeniedPath = "/account/denied";
            })
            .AddAutomaticTokenManagement()
            .AddOpenIdConnect("oidc", options =>
            {
                options.Authority    = "https://demo.identityserver.io";
                options.ClientId     = "native.code";
                options.ClientSecret = "secret";
                options.ResponseType = "code";

                options.SaveTokens = true;
                options.GetClaimsFromUserInfoEndpoint = true;

                options.Scope.Clear();
                options.Scope.Add("openid");
                options.Scope.Add("profile");
                options.Scope.Add("email");
                options.Scope.Add("offline_access");
                options.Scope.Add("api");

                options.ClaimActions.MapAllExcept("iss", "nbf", "exp", "aud", "nonce", "iat", "c_hash", "at_hash");

                options.TokenValidationParameters = new TokenValidationParameters
                {
                    NameClaimType = "name",
                    RoleClaimType = "role"
                };

                options.Events.OnRedirectToIdentityProvider = context =>
                {
                    // only modify requests to the authorization endpoint
                    if (context.ProtocolMessage.RequestType == OpenIdConnectRequestType.Authentication)
                    {
                        // generate code_verifier
                        var codeVerifier = CryptoRandom.CreateUniqueId(32);

                        // store codeVerifier for later use
                        context.Properties.Items.Add(OidcConstants.TokenRequest.CodeVerifier, codeVerifier);

                        // create code_challenge
                        string codeChallenge;
                        using (var sha256 = SHA256.Create())
                        {
                            var challengeBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(codeVerifier));
                            codeChallenge      = Base64Url.Encode(challengeBytes);
                        }

                        // add code_challenge and code_challenge_method to request
                        context.ProtocolMessage.Parameters.Add(OidcConstants.AuthorizeRequest.CodeChallenge, codeChallenge);
                        context.ProtocolMessage.Parameters.Add(OidcConstants.AuthorizeRequest.CodeChallengeMethod, OidcConstants.CodeChallengeMethods.Sha256);
                    }

                    return(Task.CompletedTask);
                };

                options.Events.OnAuthorizationCodeReceived = context =>
                {
                    // only when authorization code is being swapped for tokens
                    if (context.TokenEndpointRequest?.GrantType == OpenIdConnectGrantTypes.AuthorizationCode)
                    {
                        // get stored code_verifier
                        if (context.Properties.Items.TryGetValue(OidcConstants.TokenRequest.CodeVerifier, out var codeVerifier))
                        {
                            // add code_verifier to token request
                            context.TokenEndpointRequest.Parameters.Add(OidcConstants.TokenRequest.CodeVerifier, codeVerifier);
                        }
                    }

                    return(Task.CompletedTask);
                };
            });
        }
コード例 #5
0
 public void SetProtected(JsonWebSignatureProtected @protected)
 {
     Protected = Base64Url.Encode(JsonConvert.SerializeObject(@protected));
 }
コード例 #6
0
 public FinalizeOrderRequest(string url, byte[] csr)
 {
     Url = url ?? throw new ArgumentNullException(nameof(url));
     Csr = Base64Url.Encode(csr);
 }
コード例 #7
0
        /// <summary>
        /// Converts a JSON web key to a URL safe string.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <returns></returns>
        public static string ToJwkString(this JsonWebKey key)
        {
            var json = JsonConvert.SerializeObject(key);

            return(Base64Url.Encode(Encoding.UTF8.GetBytes(json)));
        }
コード例 #8
0
 public JsonWebEncyption(string message, JsonHeader protectedHeader, string aad = null)
 {
     _message         = Base64Url.Encode(message);
     _protectedHeader = protectedHeader;
     _aad             = aad != null?Base64Url.Encode(aad) : null;
 }
コード例 #9
0
 /// <summary>
 /// Calculates the key id for a given x509 certificate
 /// </summary>
 /// <param name="certificate"></param>
 /// <returns>kid</returns>
 public Task <string> GetKidAsync(X509Certificate2 certificate)
 {
     return(Task.FromResult(Base64Url.Encode(certificate.GetCertHash())));
 }
コード例 #10
0
ファイル: Startup.cs プロジェクト: P7CoreOrg/AspNetCore.Pkce
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc();

            services.AddAuthentication(options =>
            {
                options.DefaultAuthenticateScheme = "cookie";
                options.DefaultSignInScheme       = "cookie";
                options.DefaultChallengeScheme    = "oidc";
            })
            .AddCookie("cookie")
            .AddOpenIdConnect("oidc", options =>
            {
                options.Authority            = "http://localhost:5000";
                options.RequireHttpsMetadata = false;     // dev only

                options.ClientId     = "pkce_client";
                options.ClientSecret = "acf2ec6fb01a4b698ba240c2b10a0243";
                options.ResponseType = "code";
                options.ResponseMode = "form_post";
                options.CallbackPath = "/signin-oidc";

                options.Events.OnRedirectToIdentityProvider = context =>
                {
                    // only modify requests to the authorization endpoint
                    if (context.ProtocolMessage.RequestType == OpenIdConnectRequestType.Authentication)
                    {
                        // generate code_verifier
                        var codeVerifier = CryptoRandom.CreateUniqueId(32);

                        // store codeVerifier for later use
                        context.Properties.Items.Add("code_verifier", codeVerifier);

                        // create code_challenge
                        string codeChallenge;
                        using (var sha256 = SHA256.Create())
                        {
                            var challengeBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(codeVerifier));
                            codeChallenge      = Base64Url.Encode(challengeBytes);
                        }

                        // add code_challenge and code_challenge_method to request
                        context.ProtocolMessage.Parameters.Add("code_challenge", codeChallenge);
                        context.ProtocolMessage.Parameters.Add("code_challenge_method", "S256");
                    }

                    return(Task.CompletedTask);
                };

                options.Events.OnAuthorizationCodeReceived = context =>
                {
                    // only when authorization code is being swapped for tokens
                    if (context.TokenEndpointRequest?.GrantType == OpenIdConnectGrantTypes.AuthorizationCode)
                    {
                        // get stored code_verifier
                        if (context.Properties.Items.TryGetValue("code_verifier", out var codeVerifier))
                        {
                            // add code_verifier to token request
                            context.TokenEndpointRequest.Parameters.Add("code_verifier", codeVerifier);
                        }
                    }

                    return(Task.CompletedTask);
                };
            });
        }
コード例 #11
0
ファイル: JsonHelper.cs プロジェクト: carbon/Acme
        public static string GetBase64UrlEncodedJson <T>(T instance)
        {
            byte[] utf8Bytes = JsonSerializer.SerializeToUtf8Bytes(instance, JSO.IgnoreNullValues);

            return(Base64Url.Encode(utf8Bytes));
        }
コード例 #12
0
        /// <summary>
        /// Add custom authentication
        /// </summary>
        /// <param name="services">IServiceCollection</param>
        /// <param name="appSettings">AppSettings</param>
        /// <returns>Self</returns>
        public static IServiceCollection AddOpenIdAuthentication(this IServiceCollection services, AppSettings appSettings)
        {
            IdentityModelEventSource.ShowPII = true;

            JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();

            services.AddAuthentication(options =>
            {
                options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme; // "Cookies"
                options.DefaultSignInScheme       = CookieAuthenticationDefaults.AuthenticationScheme; // "Cookies"
                options.DefaultChallengeScheme    = "oidc";
            })
            .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme)
            .AddOpenIdConnect("oidc", options =>
            {
                const string CODE_VERIFIER_KEY         = "code_verifier";
                const string CODE_CHALLENGE_KEY        = "code_challenge";
                const string CODE_CHALLENGE_METHOD_KEY = "code_challenge_method";

                // Get config values from AppSetting file
                string oidcServerBaseUrl       = appSettings?.Host.OidcServer;
                bool isRequireHttpsMetadata    = !string.IsNullOrEmpty(oidcServerBaseUrl) && oidcServerBaseUrl.StartsWith("https");
                options.Authority              = string.IsNullOrEmpty(oidcServerBaseUrl) ? "https://localhost:6001" : oidcServerBaseUrl;
                options.RequireHttpsMetadata   = isRequireHttpsMetadata;
                options.MetadataAddress        = $"{oidcServerBaseUrl}/.well-known/openid-configuration";
                options.BackchannelHttpHandler = AuthMetadataUtils.GetHttpHandler();

                options.ClientId     = "PkceCodeBackend";
                options.ClientSecret = "secret";
                options.ResponseType = "code";
                options.ResponseMode = "form_post";
                options.CallbackPath = "/signin-oidc";

                options.SaveTokens = true;
                options.Scope.Add(appSettings?.AuthOptions?.Audience);
                options.Scope.Add("offline_access"); // Get refresh token

                options.Events.OnRedirectToIdentityProvider = context =>
                {
                    // only modify requests to the authorization endpoint
                    if (context.ProtocolMessage.RequestType == OpenIdConnectRequestType.Authentication)
                    {
                        // generate code_verifier
                        var codeVerifier = CryptoRandom.CreateUniqueId(32);

                        // store codeVerifier for later use
                        context.Properties.Items.Remove(CODE_VERIFIER_KEY);
                        context.Properties.Items.Add(CODE_VERIFIER_KEY, codeVerifier);

                        // create code_challenge
                        string codeChallenge;
                        using (var sha256 = SHA256.Create())
                        {
                            var challengeBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(codeVerifier));
                            codeChallenge      = Base64Url.Encode(challengeBytes);
                        }

                        // add code_challenge and code_challenge_method to request
                        context.ProtocolMessage.Parameters.Remove(CODE_CHALLENGE_KEY);
                        context.ProtocolMessage.Parameters.Remove(CODE_CHALLENGE_METHOD_KEY);
                        context.ProtocolMessage.Parameters.Add(CODE_CHALLENGE_KEY, codeChallenge);
                        context.ProtocolMessage.Parameters.Add(CODE_CHALLENGE_METHOD_KEY, "S256");
                    }

                    return(Task.CompletedTask);
                };

                options.Events.OnAuthorizationCodeReceived = context =>
                {
                    // only when authorization code is being swapped for tokens
                    if (context.TokenEndpointRequest?.GrantType == OpenIdConnectGrantTypes.AuthorizationCode)
                    {
                        // get stored code_verifier
                        if (context.Properties.Items.TryGetValue(CODE_VERIFIER_KEY, out var codeVerifier))
                        {
                            // add code_verifier to token request
                            context.TokenEndpointRequest.Parameters.Add(CODE_VERIFIER_KEY, codeVerifier);
                        }
                    }

                    return(Task.CompletedTask);
                };
            });

            return(services);
        }
コード例 #13
0
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddCors();
            services.AddMvc();

            services.AddAuthentication(options =>
            {
                options.DefaultAuthenticateScheme = "cookie";
                options.DefaultSignInScheme       = "cookie";
                options.DefaultChallengeScheme    = "oidc";
            }).AddIdentityServerAuthentication(options =>
            {
                options.Authority            = "http://localhost:5000"; // auth server base endpoint (will use to search for disco doc)
                options.ApiName              = "demo_api";              // required audience of access tokens
                options.RequireHttpsMetadata = false;                   // dev only!
            })
            .AddCookie("cookie")
            .AddOpenIdConnect("oidc", options =>
            {
                options.Authority            = "http://localhost:5000";
                options.RequireHttpsMetadata = false;    // dev only
                options.ClientId             = "demo_api_swagger";
                options.ClientSecret         = "acf2ec6fb01a4b698ba240c2b10a0243";
                options.ResponseType         = "code";
                options.ResponseMode         = "form_post";
                options.CallbackPath         = "/oauth2-redirect.html";
                options.Events.OnRedirectToIdentityProvider = context =>
                {
                    // only modify requests to the authorization endpoint
                    if (context.ProtocolMessage.RequestType == OpenIdConnectRequestType.Authentication)
                    {
                        // generate code_verifier
                        var codeVerifier = CryptoRandom.CreateUniqueId(32);

                        // store codeVerifier for later use
                        context.Properties.Items.Add("code_verifier", codeVerifier);

                        // create code_challenge
                        string codeChallenge;
                        using (var sha256 = SHA256.Create())
                        {
                            var challengeBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(codeVerifier));
                            codeChallenge      = Base64Url.Encode(challengeBytes);
                        }

                        // add code_challenge and code_challenge_method to request
                        context.ProtocolMessage.Parameters.Add("code_challenge", codeChallenge);
                        context.ProtocolMessage.Parameters.Add("code_challenge_method", "S256");
                    }

                    return(Task.CompletedTask);
                };

                options.Events.OnAuthorizationCodeReceived = context =>
                {
                    // only when authorization code is being swapped for tokens
                    if (context.TokenEndpointRequest?.GrantType == OpenIdConnectGrantTypes.AuthorizationCode)
                    {
                        // get stored code_verifier
                        if (context.Properties.Items.TryGetValue("code_verifier", out var codeVerifier))
                        {
                            // add code_verifier to token request
                            context.TokenEndpointRequest.Parameters.Add("code_verifier", codeVerifier);
                        }
                    }

                    return(Task.CompletedTask);
                };
            });

            services.AddSwaggerGen(options =>
            {
                options.SwaggerDoc("v1", new Info {
                    Title = "Protected API", Version = "v1"
                });

                options.AddSecurityDefinition("oauth2", new OAuth2Scheme
                {
                    Flow             = "authorizationCode", // just get token via browser (suitable for swagger SPA)
                    AuthorizationUrl = "http://localhost:5000/connect/authorize",
                    TokenUrl         = "http://localhost:5000/connect/token",
                    Scopes           = new Dictionary <string, string> {
                        { "demo_api", "Demo API - full access" }
                    },
                });

                options.OperationFilter <AuthorizeCheckOperationFilter>(); // Required to use access token
            });
        }
コード例 #14
0
ファイル: CryptoUtils.cs プロジェクト: kennyvv/MiNET-1.2
        public static byte[] EncodeSkinJwt(CngKey newKey)
        {
            byte[] t  = ImportECDsaCngKeyFromCngKey(newKey.Export(CngKeyBlobFormat.EccPrivateBlob));
            CngKey tk = CngKey.Import(t, CngKeyBlobFormat.EccPrivateBlob);

            ECDiffieHellmanCng ecKey = new ECDiffieHellmanCng(newKey);

            ecKey.HashAlgorithm         = CngAlgorithm.Sha256;
            ecKey.KeyDerivationFunction = ECDiffieHellmanKeyDerivationFunction.Hash;

            var b64Key = Base64Url.Encode(ecKey.PublicKey.ToDerEncoded());

            Skin skin = new Skin
            {
                Slim     = false,
                SkinData = Encoding.Default.GetBytes(new string('Z', 8192)),
                SkinId   = "Standard_Custom"
            };

            string skin64 = Convert.ToBase64String(skin.SkinData);


            //{
            //	"ADRole": 2,
            //	"ClientRandomId": 4670680294016914277,
            //	"CurrentInputMode": 2,
            //	"DefaultInputMode": 2,
            //	"DeviceModel": "SAMSUNG GT-P5210",
            //	"DeviceOS": 1,
            //	"GameVersion": "1.1.0.4",
            //	"GuiScale": 0,
            //	"LanguageCode": "en_US",
            //	"ServerAddress": "yodamine.com:19132",
            //	"SkinData": "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79m9/+zUuP/v2r//8t/I//Ldwv/y3cL/7NS4/+zUuP/v2r//7NS4//LfyP/y3cL/8t3C/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABkQSz/ZEEs/2RBLP9kQSz/KCgo/ygoKP8oKCj/KCgo/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6J1M/3q1d/96r3f/2LqU/+vTs//YupT/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA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",
            //	"SkinId": "Standard_Alex",
            //	"TenantId": "",
            //	"UIProfile": 1
            //}

            string skinData = $@"
{{
	""ADRole"": 0,
	""ClientRandomId"": {new Random().Next()},
	""CurrentInputMode"": 1,
	""DefaultInputMode"": 1,
	""DeviceModel"": ""MINET CLIENT"",
	""DeviceOS"": 7,
	""GameVersion"": ""1.2.0.15"",
	""GuiScale"": 0,
	""LanguageCode"": ""en_US"",
	""ServerAddress"": ""yodamine.com:19132"",
	""SkinData"": ""{skin64}"",
	""SkinId"": ""{skin.SkinId}"",
	""TenantId"": ""75a3f792-a259-4428-9a8d-4e832fb960e4"",
	""UIProfile"": 0
}}";

            string val = JWT.Encode(skinData, tk, JwsAlgorithm.ES384, new Dictionary <string, object> {
                { "x5u", b64Key }
            });

            return(Encoding.UTF8.GetBytes(val));
        }
コード例 #15
0
 void IJsonSerializable.WriteProperties(Utf8JsonWriter json)
 {
     json.WriteString(s_valuePropertyNameBytes, Base64Url.Encode(Value));
 }
コード例 #16
0
ファイル: CryptoUtils.cs プロジェクト: NiclasOlofsson/MiNET
 public static string EncodeBase64Url(this byte[] input)
 {
     return(Base64Url.Encode(input));
 }
コード例 #17
0
        /// <summary>
        /// Creates the JWK document.
        /// </summary>
        public virtual async Task <IEnumerable <Models.JsonWebKey> > CreateJwkDocumentAsync()
        {
            var webKeys            = new List <Models.JsonWebKey>();
            var signingCredentials = await Keys.GetSigningCredentialsAsync();

            var algorithm = signingCredentials?.Algorithm ?? Constants.SigningAlgorithms.RSA_SHA_256;

            foreach (var key in await Keys.GetValidationKeysAsync())
            {
                if (key is X509SecurityKey x509Key)
                {
                    var cert64     = Convert.ToBase64String(x509Key.Certificate.RawData);
                    var thumbprint = Base64Url.Encode(x509Key.Certificate.GetCertHash());

                    var pubKey     = x509Key.PublicKey as RSA;
                    var parameters = pubKey.ExportParameters(false);
                    var exponent   = Base64Url.Encode(parameters.Exponent);
                    var modulus    = Base64Url.Encode(parameters.Modulus);

                    var webKey = new Models.JsonWebKey
                    {
                        kty = "RSA",
                        use = "sig",
                        kid = x509Key.KeyId,
                        x5t = thumbprint,
                        e   = exponent,
                        n   = modulus,
                        x5c = new[] { cert64 },
                        alg = algorithm
                    };

                    webKeys.Add(webKey);
                    continue;
                }

                if (key is RsaSecurityKey rsaKey)
                {
                    var parameters = rsaKey.Rsa?.ExportParameters(false) ?? rsaKey.Parameters;
                    var exponent   = Base64Url.Encode(parameters.Exponent);
                    var modulus    = Base64Url.Encode(parameters.Modulus);

                    var webKey = new Models.JsonWebKey
                    {
                        kty = "RSA",
                        use = "sig",
                        kid = rsaKey.KeyId,
                        e   = exponent,
                        n   = modulus,
                        alg = algorithm
                    };

                    webKeys.Add(webKey);
                }

                if (key is JsonWebKey jsonWebKey)
                {
                    var webKey = new Models.JsonWebKey
                    {
                        kty = jsonWebKey.Kty,
                        use = jsonWebKey.Use ?? "sig",
                        kid = jsonWebKey.Kid,
                        x5t = jsonWebKey.X5t,
                        e   = jsonWebKey.E,
                        n   = jsonWebKey.N,
                        x5c = jsonWebKey.X5c?.Count == 0 ? null : jsonWebKey.X5c.ToArray(),
                        alg = jsonWebKey.Alg
                    };

                    webKeys.Add(webKey);
                }
            }

            return(webKeys);
        }
コード例 #18
0
        public void Configuration(IAppBuilder app)
        {
            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                AuthenticationType = "cookie"
            });

            app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
            {
                ClientId    = "mvc.owin",
                Authority   = "http://localhost:5000",
                RedirectUri = "http://localhost:5001/",
                Scope       = "openid profile api1",

                SignInAsAuthenticationType = "cookie",

                RequireHttpsMetadata = false,
                UseTokenLifetime     = false,

                RedeemCode   = true,
                SaveTokens   = true,
                ClientSecret = "secret",

                ResponseType = "code",
                ResponseMode = "query",

                Notifications = new OpenIdConnectAuthenticationNotifications
                {
                    RedirectToIdentityProvider = n =>
                    {
                        if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.Authentication)
                        {
                            // set PKCE parameters
                            var codeVerifier = CryptoRandom.CreateUniqueId(32);

                            string codeChallenge;
                            using (var sha256 = SHA256.Create())
                            {
                                var challengeBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(codeVerifier));
                                codeChallenge      = Base64Url.Encode(challengeBytes);
                            }

                            n.ProtocolMessage.SetParameter("code_challenge", codeChallenge);
                            n.ProtocolMessage.SetParameter("code_challenge_method", "S256");

                            // remember code_verifier (adapted from OWIN nonce cookie)
                            RememberCodeVerifier(n, codeVerifier);
                        }

                        return(Task.CompletedTask);
                    },
                    AuthorizationCodeReceived = n =>
                    {
                        // get code_verifier
                        var codeVerifier = RetrieveCodeVerifier(n);

                        // attach code_verifier
                        n.TokenEndpointRequest.SetParameter("code_verifier", codeVerifier);

                        return(Task.CompletedTask);
                    }
                }
            });
        }
コード例 #19
0
        //For more information on configuring authentication, please visit http://go.microsoft.com/fwlink/?LinkId=301864
        public void ConfigureAuth(IAppBuilder app)
        {
            // Workaround Middleware for Katana Bug #197
            // Bug fix: Do not attempt to update cookies if headers have been sent.
            // https://github.com/Sustainsys/owin-cookie-saver
            app.UseKentorOwinCookieSaver();

            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                // uses the AuthenticationType defined by OpenIDConnect middleware.
                AuthenticationType = CookieAuthenticationDefaults.AuthenticationType,
                ExpireTimeSpan     = TimeSpan.FromMinutes(30),
                SlidingExpiration  = true
            });

            // Authorization Code Flow with Proof Key for Code Exchange (PKCE)
            // https://auth0.com/docs/flows/concepts/auth-code-pkce
            app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
            {
                Authority             = "https://idp.example.com/",
                ClientId              = "myclient",
                RedirectUri           = "https://localhost:44361",
                CallbackPath          = new PathString("/"), // *** Critical to prevent infinite loop, when running in server *** Also dont forget to include virtual diretory name, if you have one.
                PostLogoutRedirectUri = "https://localhost:44361",

                // indicates idp to return authorization code. id_token is not returned, providing us the extra layer of security.
                ResponseType = OpenIdConnectResponseType.Code,

                // indicates idp to return code in querystring
                ResponseMode = OpenIdConnectResponseMode.Query,

                Scope = "openid profile partyAPI platformAPI offline_access",

                // this value determines the value of the AuthenticationType property of the ClaimsPrincipal/ClaimsIdentity generated from the incoming token.
                // if the cookie middleware finds this in an AuthenticationResponseGrant, that’s what the cookie middleware uses to determine whether such ClaimsPrincipal/ ClaimsIdentity should be used for creating a session.
                SignInAsAuthenticationType = CookieAuthenticationDefaults.AuthenticationType,

                // default is true, set it to false to decouple the session validity time from the token expires time.
                UseTokenLifetime = false,

                // default is true, but we explicitly set it, so that when working with local idp, we can change to false.
                RequireHttpsMetadata = true,

                RedeemCode = true, // required for PKCE
                SaveTokens = true,

                Notifications = new OpenIdConnectAuthenticationNotifications
                {
                    RedirectToIdentityProvider = async n =>
                    {
                        if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.Authentication)
                        {
                            // generate code verifier and code challenge
                            var codeVerifier = CryptoRandom.CreateUniqueId(32);

                            string codeChallenge;
                            using (var sha256 = SHA256.Create())
                            {
                                var challengeBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(codeVerifier));
                                codeChallenge      = Base64Url.Encode(challengeBytes);
                            }

                            // set code_challenge parameter on authorization request
                            n.ProtocolMessage.SetParameter("code_challenge", codeChallenge);
                            n.ProtocolMessage.SetParameter("code_challenge_method", "S256");

                            // remember code verifier in cookie (adapted from OWIN nonce cookie)
                            n.RememberCodeVerifier(codeVerifier);
                        }

                        // if signing out, add the id_token_hint
                        if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.Logout)
                        {
                            var result      = await n.OwinContext.Authentication.AuthenticateAsync(CookieAuthenticationDefaults.AuthenticationType);
                            var idTokenHint = result.Properties.Dictionary[OpenIdConnectParameterNames.IdToken];
                            if (idTokenHint != null)
                            {
                                n.ProtocolMessage.IdTokenHint = idTokenHint;
                            }
                        }

                        await Task.FromResult(0);
                    },
                    AuthorizationCodeReceived = async n =>
                    {
                        // get code verifier from cookie
                        var codeVerifier = n.RetrieveCodeVerifier();

                        // attach code_verifier on token request
                        n.TokenEndpointRequest.SetParameter("code_verifier", codeVerifier);

                        await Task.FromResult(0);
                    },
                    // after authentication, inject custom agent claims to the OWIN Identity
                    SecurityTokenValidated = async n =>
                    {
                        var accessToken = n.ProtocolMessage.AccessToken;

                        // add custom claims
                        var claimsIdentify = n.AuthenticationTicket.Identity;

                        var customeClaims = new List <Claim>
                        {
                            new Claim(ClaimTypes.Role, "SystemAdmin"),
                        };

                        claimsIdentify.AddClaims(customeClaims);

                        await Task.FromResult(0);
                    }
                }
            });
        }
コード例 #20
0
        public void JwtHeaderEncode(string base64, string raw)
        {
            var encode = Base64Url.Encode(raw);

            encode.Should().Be(base64);
        }
コード例 #21
0
        /// <summary>
        /// Finalize order.
        /// </summary>
        /// <param name="AccountLocation">Account location.</param>
        /// <param name="FinalizeLocation">Finalize location.</param>
        /// <param name="CertificateRequest">Certificate request.</param>
        /// <returns>New order object.</returns>
        public async Task <AcmeOrder> FinalizeOrder(Uri AccountLocation, Uri FinalizeLocation, CertificateRequest CertificateRequest)
        {
            byte[]       CSR      = CertificateRequest.BuildCSR();
            AcmeResponse Response = await this.POST(FinalizeLocation, AccountLocation,
                                                    new KeyValuePair <string, object>("csr", Base64Url.Encode(CSR)));

            return(new AcmeOrder(this, AccountLocation, Response.Location, Response.Payload, Response.ResponseMessage));
        }
コード例 #22
0
ファイル: JWT.cs プロジェクト: kaustubh007/virgil-sdk-net
 private string BodyBase64()
 {
     return(Base64Url.Encode(Bytes.FromString(Configuration.Serializer.Serialize(this.BodyContent))));
 }
コード例 #23
0
ファイル: MinetCrytopTest.cs プロジェクト: oizma/MiNET
        public void TestJWTHandling()
        {
            CngKey newKey = CngKey.Create(CngAlgorithm.ECDiffieHellmanP384, null, new CngKeyCreationParameters()
            {
                ExportPolicy = CngExportPolicies.AllowPlaintextExport, KeyUsage = CngKeyUsages.AllUsages
            });

            byte[] t  = CryptoUtils.ImportECDsaCngKeyFromCngKey(newKey.Export(CngKeyBlobFormat.EccPrivateBlob));
            CngKey tk = CngKey.Import(t, CngKeyBlobFormat.EccPrivateBlob);

            Assert.AreEqual(CngAlgorithmGroup.ECDsa, tk.AlgorithmGroup);

            ECDiffieHellmanCng ecKey = new ECDiffieHellmanCng(newKey);

            ecKey.HashAlgorithm         = CngAlgorithm.Sha256;
            ecKey.KeyDerivationFunction = ECDiffieHellmanKeyDerivationFunction.Hash;

            var             b64Key          = Base64Url.Encode(ecKey.PublicKey.GetDerEncoded());
            string          test            = $@"
{{ 
	""exp"": 1464983845, 
	""extraData"": {{ 
		""displayName"": ""gurunx"",	
		""identity"": ""af6f7c5e -fcea-3e43-bf3a-e005e400e578""	
	}},	
	""identityPublicKey"": ""{b64Key}"",
	""nbf"": 1464983844
}}";
            CertificateData certificateData = new CertificateData
            {
                Exp       = 1464983845,
                ExtraData = new ExtraData
                {
                    DisplayName = "gurun",
                    Identity    = "af6f7c5e -fcea-3e43-bf3a-e005e400e578",
                },
                IdentityPublicKey = b64Key,
                Nbf = 1464983844,
            };

            JWT.JsonMapper = new NewtonsoftMapper();

            string val = JWT.Encode(certificateData, tk, JwsAlgorithm.ES384, new Dictionary <string, object> {
                { "x5u", b64Key }
            });

            Console.WriteLine(val);

            Assert.AreEqual(b64Key, JWT.Headers(val)["x5u"]);
            //Assert.AreEqual("", string.Join(";", JWT.Headers(val)));
            //Assert.AreEqual(test, JWT.Payload(val));

            Console.WriteLine(JWT.Payload(val));


            IDictionary <string, dynamic> headers = JWT.Headers(val);

            if (headers.ContainsKey("x5u"))
            {
                string certString = headers["x5u"];

                // Validate
                CngKey          importKey = CryptoUtils.ImportECDsaCngKeyFromString(certString);
                CertificateData data      = JWT.Decode <CertificateData>(val, importKey);
                Assert.NotNull(data);
                Assert.AreEqual(certificateData.Exp, data.Exp);
                Assert.AreEqual(certificateData.IdentityPublicKey, data.IdentityPublicKey);
                Assert.AreEqual(certificateData.Nbf, data.Nbf);
                Assert.NotNull(data.ExtraData);
                Assert.AreEqual(certificateData.ExtraData.DisplayName, data.ExtraData.DisplayName);
                Assert.AreEqual(certificateData.ExtraData.Identity, data.ExtraData.Identity);
            }
        }
コード例 #24
0
ファイル: JWT.cs プロジェクト: kaustubh007/virgil-sdk-net
 private string SignatureBase64()
 {
     return(Base64Url.Encode(this.SignatureData));
 }
コード例 #25
0
 public void SetPayload(object payload)
 {
     Payload = Base64Url.Encode(JsonConvert.SerializeObject(payload));
 }
コード例 #26
0
 public string Base64UrlEncode(byte[] arg)
 {
     return(Base64Url.Encode(arg));
 }
コード例 #27
0
ファイル: OAuth2Client.cs プロジェクト: johnsmilee0611/OIDC
        private static string CreateUrl(string endpoint
                                        , string clientId
                                        , string scope
                                        , string redirectUri
                                        , string responseType
                                        , string responseMode
                                        , string maxAge
                                        , string codeVerifier
                                        , string state  = null
                                        , string prompt = null
                                        , string nonce  = null)
        {
            string str = string.Format("{0}?client_id={1}&scope={2}&redirect_uri={3}&response_type={4}"
                                       , endpoint
                                       , ApplicationSettings.UrlEncode(clientId)
                                       , ApplicationSettings.UrlEncode(scope)
                                       , ApplicationSettings.UrlEncode(redirectUri)
                                       , ApplicationSettings.UrlEncode(responseType));

            var codeChallengeMethod = ApplicationSettings.CodeChallengeMethod;

            if (responseType.Contains("code") && codeChallengeMethod.ToLower() != "none")
            {
                var codeChallenge = codeVerifier;
                if (codeChallengeMethod == "S256")
                {
                    using (var sha256 = SHA256.Create())
                    {
                        var challengeBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(codeVerifier));
                        codeChallenge = Base64Url.Encode(challengeBytes);
                    }
                }

                str = string.Format("{0}&code_challenge={1}&code_challenge_method={2}", str,
                                    ApplicationSettings.UrlEncode(codeChallenge),
                                    ApplicationSettings.UrlEncode(codeChallengeMethod));
            }

            if (ApplicationSettings.UsingRequestObject != "true")
            {
                if (!string.IsNullOrEmpty(maxAge))
                {
                    str = string.Format("{0}&max_age={1}", str, ApplicationSettings.UrlEncode(maxAge));
                }
                if (!string.IsNullOrEmpty(responseMode))
                {
                    str = string.Format("{0}&response_mode={1}", str, ApplicationSettings.UrlEncode(responseMode));
                }
                if (!string.IsNullOrWhiteSpace(state))
                {
                    str = string.Format("{0}&state={1}", str, ApplicationSettings.UrlEncode(state));
                }
                if (!string.IsNullOrWhiteSpace(prompt))
                {
                    str = string.Format("{0}&prompt={1}", str, ApplicationSettings.UrlEncode(prompt));
                }
                if (!string.IsNullOrWhiteSpace(nonce))
                {
                    str = string.Format("{0}&nonce={1}", str, ApplicationSettings.UrlEncode(nonce));
                }
            }
            else
            {
                var claimsIdentify = new ClaimsIdentity();
                claimsIdentify.AddClaim(new Claim("client_id", clientId));
                claimsIdentify.AddClaim(new Claim("response_type", responseType));
                claimsIdentify.AddClaim(new Claim("scope", scope));
                claimsIdentify.AddClaim(new Claim("redirect_uri", redirectUri));
                claimsIdentify.AddClaim(new Claim("max_age", maxAge));
                claimsIdentify.AddClaim(new Claim("response_mode", responseMode));
                claimsIdentify.AddClaim(new Claim("state", state));
                claimsIdentify.AddClaim(new Claim("prompt", prompt));
                claimsIdentify.AddClaim(new Claim("nonce", nonce));

                string token;
                if (ApplicationSettings.SignRequestObject == "true")
                {
                    var securityTokenDescriptor = new SecurityTokenDescriptor
                    {
                        Subject  = claimsIdentify,
                        Issuer   = clientId,
                        IssuedAt = DateTime.UtcNow,
                        Expires  = DateTime.UtcNow.AddYears(10),
                        Audience = endpoint
                    };
                    var signingCertificate = LoadCertificate(StoreName.My, StoreLocation.LocalMachine, ApplicationSettings.ClientCertificate);
                    securityTokenDescriptor.SigningCredentials = new X509SigningCredentials(signingCertificate, "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256");
                    token = new JwtSecurityTokenHandler().CreateEncodedJwt(securityTokenDescriptor);
                }
                else
                {
                    var jwtSecurityToken = new JwtSecurityTokenHandler().CreateJwtSecurityToken(clientId, endpoint, claimsIdentify, DateTime.UtcNow, DateTime.UtcNow.AddYears(10), DateTime.UtcNow);
                    token = "eyJhbGciOiJub25lIn0" + "." + jwtSecurityToken.EncodedPayload + ".";
                }

                str += "&request=" + token;
            }

            return(str);
        }
コード例 #28
0
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();

            services.AddControllersWithViews();

            services.AddAuthentication(options => {
                options.DefaultScheme          = "Cookies";
                options.DefaultChallengeScheme = "oidc";
            })
            .AddCookie("Cookies")
            .AddOpenIdConnect("oidc", options => {
                options.Authority            = "http://localhost:8000";
                options.RequireHttpsMetadata = false;
                options.ClientId             = "mvc";
                options.ClientSecret         = "mvc-secret";
                options.ResponseType         = "code";
                options.UsePkce = true;

                options.SaveTokens = true;

                options.GetClaimsFromUserInfoEndpoint = true;

                options.Scope.Add("address");
                options.ClaimActions.MapJsonKey("address", "address");
                options.Scope.Add("security_info");
                options.ClaimActions.MapJsonKey("sec_zone", "sec_zone");
                options.ClaimActions.MapJsonKey("sec_exp", "sec_exp");

                options.Scope.Add("offline_access");

                options.Events = new OpenIdConnectEvents {
                    OnRemoteFailure = ctx => {
                        WriteLine(".....OnRemoteFailure");
                        WriteLine(ctx.Failure.Message);

                        ctx.HandleResponse();
                        return(Task.FromResult(0));
                    },
                    OnRedirectToIdentityProvider = ctx => {
                        // only modify requests to the authorization endpoint
                        if (ctx.ProtocolMessage.RequestType == OpenIdConnectRequestType.Authentication)
                        {
                            // generate code_verifier
                            var codeVerifier = CryptoRandom.CreateUniqueId(32);

                            // store codeVerifier for later use
                            if (ctx.Properties.Items.ContainsKey("code_verifier"))
                            {
                                ctx.Properties.Items["code_verifier"] = codeVerifier;
                            }
                            else
                            {
                                ctx.Properties.Items.Add("code_verifier", codeVerifier);
                            }

                            // create code_challenge
                            string codeChallenge;
                            using (var sha256 = SHA256.Create())
                            {
                                var challengeBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(codeVerifier));
                                codeChallenge      = Base64Url.Encode(challengeBytes);
                            }

                            // add code_challenge and code_challenge_method to request
                            if (ctx.ProtocolMessage.Parameters.ContainsKey("code_challenge"))
                            {
                                ctx.ProtocolMessage.Parameters["code_challenge"]        = codeChallenge;
                                ctx.ProtocolMessage.Parameters["code_challenge_method"] = "S256";
                            }
                            else
                            {
                                ctx.ProtocolMessage.Parameters.Add("code_challenge", codeChallenge);
                                ctx.ProtocolMessage.Parameters.Add("code_challenge_method", "S256");
                            }
                        }

                        return(Task.CompletedTask);
                    },
                    OnAuthorizationCodeReceived = ctx => {
                        // only when authorization code is being swapped for tokens
                        if (ctx.TokenEndpointRequest?.GrantType == OpenIdConnectGrantTypes.AuthorizationCode)
                        {
                            // get stored code_verifier
                            if (ctx.Properties.Items.TryGetValue("code_verifier", out var codeVerifier))
                            {
                                // add code_verifier to token request
                                ctx.TokenEndpointRequest.Parameters.Add("code_verifier", codeVerifier);
                            }
                        }

                        return(Task.CompletedTask);
                    }
                };
            });
コード例 #29
0
        private async Task <IEndpointResult> ExecuteJwksAsync(HttpContext context)
        {
            _logger.LogDebug("Start key discovery request");

            if (_options.DiscoveryOptions.ShowKeySet == false)
            {
                _logger.LogInformation("Key discovery disabled. 404.");
                return(new StatusCodeResult(404));
            }

            var webKeys = new List <Models.JsonWebKey>();

            foreach (var key in await _keys.GetKeysAsync())
            {
                // todo
                //if (!(key is AsymmetricSecurityKey) &&
                //     !key.IsSupportedAlgorithm(SecurityAlgorithms.RsaSha256Signature))
                //{
                //    var error = "signing key is not asymmetric and does not support RS256";
                //    _logger.LogError(error);
                //    throw new InvalidOperationException(error);
                //}

                var x509Key = key as X509SecurityKey;
                if (x509Key != null)
                {
                    var cert64     = Convert.ToBase64String(x509Key.Certificate.RawData);
                    var thumbprint = Base64Url.Encode(x509Key.Certificate.GetCertHash());

                    var pubKey     = x509Key.PublicKey as RSA;
                    var parameters = pubKey.ExportParameters(false);
                    var exponent   = Base64Url.Encode(parameters.Exponent);
                    var modulus    = Base64Url.Encode(parameters.Modulus);

                    var webKey = new Models.JsonWebKey
                    {
                        kty = "RSA",
                        use = "sig",
                        kid = x509Key.KeyId,
                        x5t = thumbprint,
                        e   = exponent,
                        n   = modulus,
                        x5c = new[] { cert64 }
                    };

                    webKeys.Add(webKey);
                    continue;
                }

                var rsaKey = key as RsaSecurityKey;
                if (rsaKey != null)
                {
                    var parameters = rsaKey.Rsa.ExportParameters(false);

                    var exponent = Base64Url.Encode(parameters.Exponent);
                    var modulus  = Base64Url.Encode(parameters.Modulus);

                    var webKey = new Models.JsonWebKey
                    {
                        kty = "RSA",
                        use = "sig",
                        kid = rsaKey.KeyId,
                        e   = exponent,
                        n   = modulus,
                    };

                    webKeys.Add(webKey);
                }
            }

            return(new JsonWebKeysResult(webKeys));
        }
コード例 #30
0
        internal string GetKid()
        {
            RSAParameters parameters = mKey.ExportParameters(false);

            return(Thumbprint("RSA", Base64Url.Encode(parameters.Exponent), Base64Url.Encode(parameters.Modulus)).Substring(0, 5));
        }