Skip to content

Commit

Permalink
Merge pull request #113 from OpenTouryoProject/JarJarmNet
Browse files Browse the repository at this point in the history
Interim report on "JAR" and "JARM" support work.
  • Loading branch information
yusukemaegawa authored Jul 7, 2019
2 parents 4af40b4 + 1123c78 commit 13acd4f
Show file tree
Hide file tree
Showing 41 changed files with 2,622 additions and 999 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,23 @@ CREATE TABLE [OAuth2Revocation](
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

CREATE TABLE [IssuedToken](
[Jti] [nvarchar](38) NOT NULL, -- PK, guid
[Value] [nvarchar](max) NULL, -- IssuedToken
[ClientID] [nvarchar](38) NOT NULL,
[Audience] [nvarchar](38) NOT NULL,
[CreatedDate] [smalldatetime] NOT NULL,
CONSTRAINT [PK.IssuedToken] PRIMARY KEY NONCLUSTERED ([Jti] ASC)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

CREATE TABLE [RequestObject](
[Urn] [nvarchar](38) NOT NULL, -- PK, guid
[Value] [nvarchar](max) NULL, -- RequestObject
[CreatedDate] [smalldatetime] NOT NULL,
CONSTRAINT [PK.RequestObject] PRIMARY KEY NONCLUSTERED ([Urn] ASC)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

-- INDEX
---- Users
Expand Down
11 changes: 11 additions & 0 deletions root/files/resource/X509/GenECDsaCertByOpenSSL.bat
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
openssl ecparam -list_curves

openssl ecparam -out private-key.pem -name prime256v1 -genkey
openssl req -new -key private-key.pem > csr.csr
openssl x509 -in csr.csr -days 365000 -req -signkey private-key.pem > _SHA256ECDSA.cer
openssl pkcs12 -export -inkey private-key.pem -in _SHA256ECDSA.cer > _SHA256ECDSA.pfx

openssl ecparam -out private-key.pem -name secp384r1 -genkey
openssl req -new -key private-key.pem > csr.csr
openssl x509 -in csr.csr -days 365000 -req -signkey private-key.pem > _SHA384ECDSA.cer
openssl pkcs12 -export -inkey private-key.pem -in _SHA384ECDSA.cer > _SHA384ECDSA.pfx

openssl ecparam -out private-key.pem -name secp521r1 -genkey
openssl req -new -key private-key.pem > csr.csr
openssl x509 -in csr.csr -days 365000 -req -signkey private-key.pem > _SHA521ECDSA.cer
openssl pkcs12 -export -inkey private-key.pem -in _SHA521ECDSA.cer > _SHA521ECDSA.pfx
12 changes: 12 additions & 0 deletions root/files/resource/X509/SHA384ECDSA.cer
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
-----BEGIN CERTIFICATE-----
MIIB0DCCAVcCCQC2AfLlMlV+KzAKBggqhkjOPQQDAjBRMQswCQYDVQQGEwJBVTET
MBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQ
dHkgTHRkMQowCAYDVQQDDAF4MCAXDTE5MDYyNTA3NDY0MVoYDzMwMTgxMDI2MDc0
NjQxWjBRMQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UE
CgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMQowCAYDVQQDDAF4MHYwEAYHKoZI
zj0CAQYFK4EEACIDYgAEqeyd2iMw8DZT7Yy3KO0mOuok1JBBdMwEuJTa81Upg06f
bVbotK8yuhDSVkzSFsw3thH6faasSDmEO4zeVNdc5LbZJprQmL7JN3NZzYUJmF1G
hQEl6QaZh+6f1QhDH0StMAoGCCqGSM49BAMCA2cAMGQCMAS6rWxZuGZ7QECfqpWI
aZnK+F5fnLumQ1LbOwXhq68yUi/3pHj/2Eb2OMLodenTBgIwPBbkMBfUx4FIekl6
DvPrt76SjQHfrZmulNG6xUAznYB9VOQk4qulTzb67A8nNPpu
-----END CERTIFICATE-----
Binary file added root/files/resource/X509/SHA384ECDSA.pfx
Binary file not shown.
14 changes: 14 additions & 0 deletions root/files/resource/X509/SHA521ECDSA.cer
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
-----BEGIN CERTIFICATE-----
MIICHDCCAX0CCQCp548b2cn2yzAKBggqhkjOPQQDAjBRMQswCQYDVQQGEwJBVTET
MBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQ
dHkgTHRkMQowCAYDVQQDDAF4MCAXDTE5MDYyNTA3NDczMloYDzMwMTgxMDI2MDc0
NzMyWjBRMQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UE
CgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMQowCAYDVQQDDAF4MIGbMBAGByqG
SM49AgEGBSuBBAAjA4GGAAQBChF1IPNct+KfoIWEvEM4vT8J+f5BzCB1syQwaDBN
4DiAMjKAI4TLibR7JOYSeNh0E4w3km1hSKmt1lmuIAbOscIBOPkkF6P3O1+wCskt
QwKzh53IKA+4i15+HsoUZ9558jtiMH6lqRwrHOEdnWHZSFHXzdudDiutdzvU3lYC
Xd3kGpkwCgYIKoZIzj0EAwIDgYwAMIGIAkIBamsrJIXEFleYv7iBj3M36OeaPuV2
HoT+LIrmWNMhMhMyJ4khJJo8gDshc5bFJl0FEkzVRKPZEo6DsVcCo/X6PVoCQgET
SdJC6fI/dbcml0R/F7TynKreJ5pxCR32WNOS8jZmfyiRqbp0NFYwtn0B73PcpZWM
bNWHN6Yt7WZm4yhbDKSoXg==
-----END CERTIFICATE-----
Binary file added root/files/resource/X509/SHA521ECDSA.pfx
Binary file not shown.
7 changes: 5 additions & 2 deletions root/programs/CommandLineTools/CreateJwkSetJson/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,15 @@ static void Main(string[] args)
#endif

// 現在の証明書のJwk
RsaPublicKeyConverter rpbkc = new RsaPublicKeyConverter(JWS_RSA.RS._256);
EccPublicKeyConverter epbkc = new EccPublicKeyConverter(JWS_ECDSA.ES._256);

JObject rsaJwkObject =
JsonConvert.DeserializeObject<JObject>(
RsaPublicKeyConverter.X509CerToJwk(CmnClientParams.RsaCerFilePath));
rpbkc.X509CerToJwk(CmnClientParams.RsaCerFilePath));
JObject ecdsaJwkObject =
JsonConvert.DeserializeObject<JObject>(
EccPublicKeyConverter.X509CerToJwk(CmnClientParams.EcdsaCerFilePath));
epbkc.X509CerToJwk(CmnClientParams.EcdsaCerFilePath));

// JwkSet.jsonファイルの存在チェック
if (!ResourceLoader.Exists(OAuth2AndOIDCParams.JwkSetFilePath, false))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ static void Main(string[] args)
#region PrivateKey
Console.WriteLine("PrivateKey:");

jwkPrivateKey = PrivateKeyConverter.RsaParamToJwk(((RSA)dsX509.X509Certificate.PrivateKey).ExportParameters(true));
RsaPrivateKeyConverter rpvkc = new RsaPrivateKeyConverter(JWS_RSA.RS._256);
jwkPrivateKey = rpvkc.ParamToJwk(((RSA)dsX509.X509Certificate.PrivateKey).ExportParameters(true));
jwkPrivateKey = CustomEncode.ToBase64UrlString(CustomEncode.StringToByte(jwkPrivateKey, CustomEncode.us_ascii));

Console.WriteLine(jwkPrivateKey);
Expand All @@ -81,19 +82,20 @@ static void Main(string[] args)
#region PublicKey
Console.WriteLine("PublicKey:");

jwkPublicKey = RsaPublicKeyConverter.ParamToJwk(((RSA)dsX509.X509Certificate.PublicKey.Key).ExportParameters(false));
RsaPublicKeyConverter rpbkc = new RsaPublicKeyConverter(JWS_RSA.RS._256);
jwkPublicKey = rpbkc.ParamToJwk(((RSA)dsX509.X509Certificate.PublicKey.Key).ExportParameters(false));
jwkPublicKey = CustomEncode.ToBase64UrlString(CustomEncode.StringToByte(jwkPublicKey, CustomEncode.us_ascii));

Console.WriteLine(jwkPublicKey);
Console.WriteLine("");
#endregion

#region Check
string jwtAssertion = JwtAssertion.CreateJwtBearerTokenFlowAssertionJWK(
string jwtAssertion = JwtAssertion.Create(
CmnClientParams.Isser, OAuth2AndOIDCParams.Audience, new TimeSpan(0, 30, 0), scopes,
CustomEncode.ByteToString(CustomEncode.FromBase64UrlString(jwkPrivateKey), CustomEncode.us_ascii));

if (JwtAssertion.VerifyJwtBearerTokenFlowAssertionJWK(
if (JwtAssertion.Verify(
jwtAssertion, out iss, out aud, out scopes, out jobj,
CustomEncode.ByteToString(CustomEncode.FromBase64UrlString(jwkPublicKey), CustomEncode.us_ascii)))
{
Expand Down
18 changes: 4 additions & 14 deletions root/programs/CommonLibrary/Co/Const.cs
Original file line number Diff line number Diff line change
Expand Up @@ -89,26 +89,16 @@ public const string Role_SystemAdminOrAdminOrUser
+ OAuth2AndOIDCConst.Scope_Email + " "
+ OAuth2AndOIDCConst.Scope_Phone + " "
+ OAuth2AndOIDCConst.Scope_Address + " "
+ OAuth2AndOIDCConst.Scope_UserID;
+ OAuth2AndOIDCConst.Scope_UserID + " "
+ OAuth2AndOIDCConst.Scope_Roles;

/// <summary>OIDCのscope</summary>
public static readonly string OidcScopes =
OAuth2AndOIDCConst.Scope_Openid + " "
+ OAuth2AndOIDCConst.Scope_Profile + " "
+ OAuth2AndOIDCConst.Scope_Email + " "
+ OAuth2AndOIDCConst.Scope_Phone + " "
+ OAuth2AndOIDCConst.Scope_Address + " "
+ OAuth2AndOIDCConst.Scope_UserID;
OAuth2AndOIDCConst.Scope_Openid + " " + StandardScopes;

/// <summary>ID連携 scope</summary>
public static readonly string IdFederationScopes =
OAuth2AndOIDCConst.Scope_Openid + " "
+ OAuth2AndOIDCConst.Scope_Profile + " "
+ OAuth2AndOIDCConst.Scope_Email + " "
+ OAuth2AndOIDCConst.Scope_Phone + " "
+ OAuth2AndOIDCConst.Scope_Address + " "
+ OAuth2AndOIDCConst.Scope_UserID + " "
+ OAuth2AndOIDCConst.Scope_Roles;
OAuth2AndOIDCConst.Scope_Openid + " " + StandardScopes;

#endregion

Expand Down
4 changes: 2 additions & 2 deletions root/programs/CommonLibrary/Extensions/FIDO/MsPassHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,8 @@ public bool ValidateSignature(
// Challengeの一致

// Load public key
RSA rsa =
RsaPublicKeyConverter.JwkToProvider(this.PublicKey);
RsaPublicKeyConverter rpkc = new RsaPublicKeyConverter(JWS_RSA.RS._256);
RSA rsa = rpkc.JwkToProvider(this.PublicKey);

// VerifyData
ret = rsa.VerifyData(
Expand Down
127 changes: 81 additions & 46 deletions root/programs/CommonLibrary/Extensions/Sts/Helper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@
using Microsoft.AspNetCore.Identity;
#endif


using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

using Touryo.Infrastructure.Framework.Authentication;
using Touryo.Infrastructure.Public.FastReflection;
Expand Down Expand Up @@ -255,39 +255,7 @@ public async Task<string> GetAccessTokenByCodeAsync(
{
return await OAuth2AndOIDCClient.GetAccessTokenByCodeAsync(
tokenEndpointUri, client_id, client_secret, redirect_uri, code);
}

/// <summary>
/// PKCE : code, code_verifierからAccess Tokenを取得する。
/// </summary>
/// <param name="tokenEndpointUri">TokenエンドポイントのUri</param>
/// <param name="client_id">client_id</param>
/// <param name="client_secret">client_secret</param>
/// <param name="redirect_uri">redirect_uri</param>
/// <param name="code">code</param>
/// <param name="code_verifier">code_verifier</param>
/// <returns>結果のJSON文字列</returns>
public async Task<string> GetAccessTokenByCodeAsync(
Uri tokenEndpointUri, string client_id, string client_secret, string redirect_uri, string code, string code_verifier)
{
return await OAuth2AndOIDCClient.GetAccessTokenByCodeAsync(
tokenEndpointUri, client_id, client_secret, redirect_uri, code, code_verifier);
}

/// <summary>
/// FAPI1 : code, code_verifierからAccess Tokenを取得する。
/// </summary>
/// <param name="tokenEndpointUri">TokenエンドポイントのUri</param>
/// <param name="redirect_uri">redirect_uri</param>
/// <param name="code">code</param>
/// <param name="assertion">assertion</param>
/// <returns>結果のJSON文字列</returns>
public async Task<string> GetAccessTokenByCodeAsync(
Uri tokenEndpointUri, string redirect_uri, string code, string assertion)
{
return await OAuth2AndOIDCClient.GetAccessTokenByCodeAsync(
tokenEndpointUri, redirect_uri, code, assertion);
}
}

/// <summary>
/// Resource Owner Password Credentials Grant
Expand Down Expand Up @@ -322,6 +290,10 @@ public async Task<string> ClientCredentialsGrantAsync(
tokenEndpointUri, client_id, client_secret, scopes);
}

#endregion

#region その他の 基本 WebAPI

/// <summary>Refresh Tokenを使用してAccess Tokenを更新する。</summary>
/// <param name="tokenEndpointUri">tokenEndpointUri</param>
/// <param name="client_id">client_id</param>
Expand Down Expand Up @@ -353,6 +325,27 @@ public async Task<string> GetUserInfoAsync(string accessToken)

#region 拡張フローのWebAPI

#region PKCE

/// <summary>
/// PKCE : code, code_verifierからAccess Tokenを取得する。
/// </summary>
/// <param name="tokenEndpointUri">TokenエンドポイントのUri</param>
/// <param name="client_id">client_id</param>
/// <param name="client_secret">client_secret</param>
/// <param name="redirect_uri">redirect_uri</param>
/// <param name="code">code</param>
/// <param name="code_verifier">code_verifier</param>
/// <returns>結果のJSON文字列</returns>
public async Task<string> GetAccessTokenByCodeAsync(
Uri tokenEndpointUri, string client_id, string client_secret, string redirect_uri, string code, string code_verifier)
{
return await OAuth2AndOIDCClient.GetAccessTokenByCodeAsync(
tokenEndpointUri, client_id, client_secret, redirect_uri, code, code_verifier);
}

#endregion

#region Revoke & Introspect

/// <summary>Revokeエンドポイントで、Tokenを無効化する。</summary>
Expand Down Expand Up @@ -388,14 +381,44 @@ public async Task<string> IntrospectTokenAsync(
#region JWT Bearer Token Flow

/// <summary>
/// Token2エンドポイントで
/// Tokenエンドポイントで
/// JWT bearer token authorizationグラント種別の要求を行う。</summary>
/// <param name="token2EndpointUri">Token2エンドポイントのUri</param>
/// <param name="tokenEndpointUri">TokenエンドポイントのUri</param>
/// <param name="assertion">string</param>
/// <returns>結果のJSON文字列</returns>
public async Task<string> JwtBearerTokenFlowAsync(Uri token2EndpointUri, string assertion)
public async Task<string> JwtBearerTokenFlowAsync(Uri tokenEndpointUri, string assertion)
{
return await OAuth2AndOIDCClient.JwtBearerTokenFlowAsync(tokenEndpointUri, assertion);
}

#endregion

#region FAPI (Financial-grade API)

/// <summary>
/// FAPI1 : code, assertionからAccess Tokenを取得する。
/// </summary>
/// <param name="tokenEndpointUri">TokenエンドポイントのUri</param>
/// <param name="redirect_uri">redirect_uri</param>
/// <param name="code">code</param>
/// <param name="assertion">assertion</param>
/// <returns>結果のJSON文字列</returns>
public async Task<string> GetAccessTokenByCodeAsync(
Uri tokenEndpointUri, string redirect_uri, string code, string assertion)
{
return await OAuth2AndOIDCClient.JwtBearerTokenFlowAsync(token2EndpointUri, assertion);
return await OAuth2AndOIDCClient.GetAccessTokenByCodeAsync(
tokenEndpointUri, redirect_uri, code, assertion);
}

/// <summary>
/// FAPI2 : RequestObjectを登録する。
/// </summary>
/// <param name="requestObjectRegUri">Uri</param>
/// <param name="requestObject">string</param>
/// <returns>結果のJSON文字列</returns>
public async Task<string> RegisterRequestObjectAsync(Uri requestObjectRegUri, string requestObject)
{
return await OAuth2AndOIDCClient.RegisterRequestObjectAsync(requestObjectRegUri, requestObject);
}

#endregion
Expand Down Expand Up @@ -887,43 +910,55 @@ public static IEnumerable<string> FilterClaimAtAuth(IEnumerable<string> scopes)
/// <param name="client_id">string</param>
/// <param name="state">string</param>
/// <param name="scopes">string[]</param>
/// <param name="claims">JObject</param>
/// <param name="nonce">string</param>
/// <param name="jti">string</param>
/// <returns>ClaimsIdentity</returns>
public static ClaimsIdentity AddClaim(ClaimsIdentity claims,
string client_id, string state, IEnumerable<string> scopes, string nonce)
public static ClaimsIdentity AddClaim(ClaimsIdentity identity,
string client_id, string state, IEnumerable<string> scopes, JObject claims, string nonce)
// string exp, string nbf, string iat, string jtiは不要(Unprotectで決定、読取専用)。
{
// 発行者の情報を含める。

#region 標準

claims.AddClaim(new Claim(OAuth2AndOIDCConst.Claim_Issuer, Config.IssuerId));
claims.AddClaim(new Claim(OAuth2AndOIDCConst.Claim_Audience, client_id));
identity.AddClaim(new Claim(OAuth2AndOIDCConst.UrnIssuerClaim, Config.IssuerId));
identity.AddClaim(new Claim(OAuth2AndOIDCConst.UrnAudienceClaim, client_id));

foreach (string scope in scopes)
{
// その他のscopeは、Claimの下記urnに組み込む。
claims.AddClaim(new Claim(OAuth2AndOIDCConst.Claim_Scopes, scope));
identity.AddClaim(new Claim(OAuth2AndOIDCConst.UrnScopesClaim, scope));
}

#endregion

#region 拡張

// OpenID Connect

// nonce
if (string.IsNullOrEmpty(nonce))
{
claims.AddClaim(new Claim(OAuth2AndOIDCConst.Claim_Nonce, state));
identity.AddClaim(new Claim(OAuth2AndOIDCConst.UrnNonceClaim, state));
}
else
{
claims.AddClaim(new Claim(OAuth2AndOIDCConst.Claim_Nonce, nonce));
identity.AddClaim(new Claim(OAuth2AndOIDCConst.UrnNonceClaim, nonce));
}

// auth_time
// AccountControllerで追加

// FAPI2 (RequestObject)
if (claims != null)
{
identity.AddClaim(new Claim(OAuth2AndOIDCConst.UrnClaimsClaim, claims.ToString()));
}

#endregion

return claims;
return identity;
}

#endregion
Expand Down
Loading

0 comments on commit 13acd4f

Please sign in to comment.