Esempio n. 1
0
        //[Authorize]
        public Dictionary <string, string> RevokeToken(FormDataCollection formData)
        {
            // 戻り値(エラー)
            Dictionary <string, string> err = new Dictionary <string, string>();

            // 変数
            string[] temp            = null;
            string   token           = formData[OAuth2AndOIDCConst.token];
            string   token_type_hint = formData[OAuth2AndOIDCConst.token_type_hint];

            // クライアント認証

            // クライアント識別子
            string authHeader = HttpContext.Current.Request.Headers[OAuth2AndOIDCConst.HttpHeader_Authorization];

            temp = authHeader.Split(' ');

            if (temp[0] == OAuth2AndOIDCConst.Basic)
            {
                temp = CustomEncode.ByteToString(
                    CustomEncode.FromBase64String(temp[1]), CustomEncode.us_ascii).Split(':');

                string clientId     = temp[0];
                string clientSecret = temp[1];

                if (!(string.IsNullOrEmpty(clientId) && string.IsNullOrEmpty(clientSecret)))
                {
                    // *.config or OAuth2Dataテーブルを参照してクライアント認証を行なう。
                    if (clientSecret == OAuth2Helper.GetInstance().GetClientSecret(clientId))
                    {
                        // 検証完了

                        if (token_type_hint == OAuth2AndOIDCConst.AccessToken)
                        {
                            // 検証
                            AccessTokenFormatJwt verifier = new AccessTokenFormatJwt();
                            AuthenticationTicket ticket   = verifier.Unprotect(token);

                            if (ticket == null)
                            {
                                // 検証失敗
                                // 検証エラー
                                err.Add("error", "invalid_request");
                                err.Add("error_description", "invalid token");
                            }
                            else
                            {
                                // 検証成功

                                // jtiの取り出し
                                Claim jti = ticket.Identity.Claims.Where(
                                    x => x.Type == OAuth2AndOIDCConst.Claim_JwtId).FirstOrDefault <Claim>();

                                // access_token取消
                                OAuth2RevocationProvider.GetInstance().Create(jti.Value);
                                return(null); // 成功
                            }
                        }
                        else if (token_type_hint == OAuth2AndOIDCConst.RefreshToken)
                        {
                            // refresh_token取消
                            if (RefreshTokenProvider.DeleteDirectly(token))
                            {
                                // 取り消し成功
                                return(null); // 成功
                            }
                            else
                            {
                                // 取り消し失敗
                                err.Add("error", "invalid_request");
                                err.Add("error_description", "invalid token");
                            }
                        }
                        else
                        {
                            // token_type_hint パラメタ・エラー
                            err.Add("error", "invalid_request");
                            err.Add("error_description", "invalid token_type_hint");
                        }
                    }
                    else
                    {
                        // クライアント認証エラー(Credential不正
                        err.Add("error", "invalid_client");
                        err.Add("error_description", "Invalid credential");
                    }
                }
                else
                {
                    // クライアント認証エラー(Credential不正
                    err.Add("error", "invalid_client");
                    err.Add("error_description", "Invalid credential");
                }
            }
            else
            {
                // クライアント認証エラー(ヘッダ不正
                err.Add("error", "invalid_request");
                err.Add("error_description", "Invalid authentication header");
            }

            return(err); // 失敗
        }
Esempio n. 2
0
        /// <summary>Unprotect</summary>
        /// <param name="jwt">JWT文字列</param>
        /// <returns>AuthenticationTicket</returns>
        public AuthenticationTicket Unprotect(string jwt)
        {
            // 空のケースあり。
            if (string.IsNullOrEmpty(jwt))
            {
                return(null);
            }

            // 検証
            JWT_RS256 jwtRS256 = new JWT_RS256(ASPNETIdentityConfig.OAuthJWT_cer, ASPNETIdentityConfig.OAuthJWTPassword);

            if (jwtRS256.Verify(jwt))
            {
                // 検証できた。

                // デシリアライズ、
                string[] temp = jwt.Split('.');
                string   json = CustomEncode.ByteToString(CustomEncode.FromBase64UrlString(temp[1]), CustomEncode.UTF_8);
                Dictionary <string, object> authTokenClaimSet = JsonConvert.DeserializeObject <Dictionary <string, object> >(json);

                // 以下の検証処理
                //  ★ "iss": accounts.google.com的な,
                //  ★ "aud": client_id(クライアント識別子)
                //  ★ "sub": ユーザーの一意識別子(uname, email)
                //  ★ "exp": JWT の有効期限(Unix時間)
                //  ☆ "jti": JWT のID(OAuth Token Revocation)

                DateTime?datetime = OAuth2RevocationProvider.GetInstance().Get((string)authTokenClaimSet["jti"]);

                if (datetime == null)
                {
                    // authToken.iss, authToken.expの検証
                    if ((string)authTokenClaimSet["iss"] == ASPNETIdentityConfig.OAuthIssuerId &&
                        OAuth2Helper.GetInstance().GetClientSecret((string)authTokenClaimSet["aud"]) != null &&
                        long.Parse((string)authTokenClaimSet["exp"]) >= DateTimeOffset.Now.ToUnixTimeSeconds())
                    {
                        // authToken.subの検証
                        // ApplicationUser を取得する。
                        ApplicationUserManager userManager
                            = HttpContext.Current.GetOwinContext().GetUserManager <ApplicationUserManager>();
                        ApplicationUser user = userManager.FindByName((string)authTokenClaimSet["sub"]); // 同期版でOK。

                        if (user != null)
                        {
                            // User Accountの場合

                            // ユーザーに対応するClaimsIdentityを生成し、
                            ClaimsIdentity identity = userManager.CreateIdentity(user, DefaultAuthenticationTypes.ExternalBearer);

                            // aud、scopes、nonceなどのClaimを追加する。
                            List <string> scopes = new List <string>();
                            foreach (string s in (JArray)authTokenClaimSet["scopes"])
                            {
                                scopes.Add(s);
                            }

                            OAuth2Helper.AddClaim(identity,
                                                  (string)authTokenClaimSet["aud"], "", scopes,  (string) authTokenClaimSet["nonce"]);

                            // その他、所定のClaimを追加する。
                            identity.AddClaim(new Claim(ASPNETIdentityConst.Claim_ExpirationTime, (string)authTokenClaimSet["exp"]));
                            identity.AddClaim(new Claim(ASPNETIdentityConst.Claim_NotBefore, (string)authTokenClaimSet["nbf"]));
                            identity.AddClaim(new Claim(ASPNETIdentityConst.Claim_IssuedAt, (string)authTokenClaimSet["iat"]));
                            identity.AddClaim(new Claim(ASPNETIdentityConst.Claim_JwtId, (string)authTokenClaimSet["jti"]));

                            // AuthenticationPropertiesの生成
                            AuthenticationProperties prop = new AuthenticationProperties();
                            prop.IssuedUtc  = DateTimeOffset.FromUnixTimeSeconds(long.Parse((string)authTokenClaimSet["iat"]));
                            prop.ExpiresUtc = DateTimeOffset.FromUnixTimeSeconds(long.Parse((string)authTokenClaimSet["exp"]));

                            AuthenticationTicket auth = new AuthenticationTicket(identity, prop);

                            // 認証結果を返す。
                            return(auth);
                        }
                        else
                        {
                            // Client Accountの場合

                            // ClaimとStoreのAudience(aud)に対応するSubject(sub)が一致するかを確認し、一致する場合のみ、認証する。
                            // ※ でないと、UserStoreから削除されたUser Accountが、Client Accountに化けることになる。
                            if ((string)authTokenClaimSet["sub"] == OAuth2Helper.GetInstance().GetClientName((string)authTokenClaimSet["aud"]))
                            {
                                // ClaimsIdentityを生成し、
                                ClaimsIdentity identity = new ClaimsIdentity(DefaultAuthenticationTypes.ExternalBearer);

                                // sub(client_idに対応するclient_name)Claimを設定する。
                                identity.AddClaim(new Claim(ClaimTypes.Name, (string)authTokenClaimSet["sub"]));

                                // aud、scopes、nonceなどのClaimを追加する。
                                List <string> scopes = new List <string>();
                                foreach (string s in (JArray)authTokenClaimSet["scopes"])
                                {
                                    scopes.Add(s);
                                }

                                OAuth2Helper.AddClaim(identity,
                                                      (string)authTokenClaimSet["aud"], "", scopes, (string)authTokenClaimSet["nonce"]);

                                // その他、所定のClaimを追加する。
                                identity.AddClaim(new Claim(ASPNETIdentityConst.Claim_ExpirationTime, (string)authTokenClaimSet["exp"]));
                                identity.AddClaim(new Claim(ASPNETIdentityConst.Claim_NotBefore, (string)authTokenClaimSet["nbf"]));
                                identity.AddClaim(new Claim(ASPNETIdentityConst.Claim_IssuedAt, (string)authTokenClaimSet["iat"]));
                                identity.AddClaim(new Claim(ASPNETIdentityConst.Claim_JwtId, (string)authTokenClaimSet["jti"]));

                                // AuthenticationPropertiesの生成
                                AuthenticationProperties prop = new AuthenticationProperties();
                                prop.IssuedUtc  = DateTimeOffset.FromUnixTimeSeconds(long.Parse((string)authTokenClaimSet["iat"]));
                                prop.ExpiresUtc = DateTimeOffset.FromUnixTimeSeconds(long.Parse((string)authTokenClaimSet["exp"]));

                                AuthenticationTicket auth = new AuthenticationTicket(identity, prop);

                                // 認証結果を返す。
                                return(auth);
                            }
                        }
                    }
                    else
                    {
                        // クレーム検証の失敗
                    }
                }
                else
                {
                    // 取り消し済み
                }
            }
            else
            {
                // JWT署名検証の失敗
            }

            // 検証、認証ナドナド、できなかった。
            return(null);
        }