diff --git a/root/files/resource/Log/Examples of rolling of date+size.xml b/root/files/resource/Log/Examples of rolling of date+size.xml deleted file mode 100644 index 0a36e651..00000000 --- a/root/files/resource/Log/Examples of rolling of date+size.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - ---- - -以下、koido Blog「Log4Netのちょっと良い設定」から引用 - - Log4Netのちょっと良い設定 - http://www.ailight.jp/Blog/koido/archive/2005/3/9/Log4Net%E3%81%AE%E3%81%A1%E3%82%87%E3%81%A3%E3%81%A8%E8%89%AF%E3%81%84%E8%A8%AD%E5%AE%9A - - 色々試してみたら、 - - - という設定で、日付と容量のローテートが実現出来ました。 - - yyyy、MM、ddに""を囲むのか、-や.に""を囲むのか分かりませんが、 - どうもDatePatternの指定の仕方がミソのようです。 diff --git a/root/files/resource/Log/Log4NetConfigTemplate.xml b/root/files/resource/Log/Log4NetConfigTemplate.xml deleted file mode 100644 index dfba2f44..00000000 --- a/root/files/resource/Log/Log4NetConfigTemplate.xml +++ /dev/null @@ -1,146 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/root/files/resource/MultiPurposeAuthSite/JwkSet.json b/root/files/resource/MultiPurposeAuthSite/JwkSet.json new file mode 100644 index 00000000..2c304625 --- /dev/null +++ b/root/files/resource/MultiPurposeAuthSite/JwkSet.json @@ -0,0 +1,18 @@ +{ + "keys": [ + { + "kty": "RSA", + "alg": "RS256", + "n": "zeoXAJoQ7EicnX6D4VzLZU7wUQcclGkrVqf-jvKHsrR8e6LCUz988JIXP6FjErsnYYBP8xteJX7qETrIRTyBzHhbMdNosm7tedUd123pzUG5SSZAtMMb8tFrLAr6bxSk1GBYmJfWHqXx3c99sefQ2x_9PY-zuO0K8-BPq8PqJek", + "e": "AQAB", + "kid": "aqAgrnvCzpW7uE1KH_IAgyyYHauYEVNUIefxPKnJKmc" + }, + { + "kty": "RSA", + "alg": "RS256", + "n": "qMkXqwXBqXX1cde6DmXuWaLSEfyhyjvdXe4Lq8C9P5wnatFL2c43PIgU4q-f_ufcCwbR49uTEQiD5ZTf9fLgclG91BBrWuTHOU12fgrJyp19VdqckYB-AGX8ZBKOb-WckTPN6ukRC82nN_trzcKNO_R5nSN2dsuLB_Geb9sxvac", + "e": "AQAB", + "kid": "KQguDe5h5cK2VcvH5T4pAQmoBSOkHc0KcL4jPB1Rsw0" + } + ] +} \ No newline at end of file diff --git a/root/files/resource/Log/SampleLogConf.xml b/root/files/resource/MultiPurposeAuthSite/Log/SampleLogConf.xml similarity index 95% rename from root/files/resource/Log/SampleLogConf.xml rename to root/files/resource/MultiPurposeAuthSite/Log/SampleLogConf.xml index 6b444eb9..7686a9c9 100644 --- a/root/files/resource/Log/SampleLogConf.xml +++ b/root/files/resource/MultiPurposeAuthSite/Log/SampleLogConf.xml @@ -37,7 +37,7 @@ - + @@ -58,7 +58,7 @@ - + @@ -79,7 +79,7 @@ - + diff --git a/root/files/resource/Sql/oracle/Create_UserStore.sql b/root/files/resource/MultiPurposeAuthSite/Sql/oracle/Create_UserStore.sql similarity index 96% rename from root/files/resource/Sql/oracle/Create_UserStore.sql rename to root/files/resource/MultiPurposeAuthSite/Sql/oracle/Create_UserStore.sql index 6f22c6e9..40dd0e8b 100644 --- a/root/files/resource/Sql/oracle/Create_UserStore.sql +++ b/root/files/resource/MultiPurposeAuthSite/Sql/oracle/Create_UserStore.sql @@ -1,119 +1,120 @@ --- For the information of using Oracle database and ODP.NET managed driver --- for the user store of multi-purpose authentication site, see the following site. --- Oracle11gXE + ODP.NET Managed Driver - マイクロソフト系技術情報 Wiki --- https://techinfoofmicrosofttech.osscons.jp/index.php?Oracle11gXE%20%2B%20ODP.NET%20Managed%20Driver - ---UserClaimsのIDENTITY - -CREATE TABLE "Users"( -- Users - "Id" NVARCHAR2(38) NOT NULL, -- PK, guid - "UserName" NVARCHAR2(256) NOT NULL, - "Email" NVARCHAR2(256) NULL, - "EmailConfirmed" NUMBER(3) NOT NULL, - "PasswordHash" NVARCHAR2(2000) NULL, - "SecurityStamp" NVARCHAR2(2000) NULL, - "PhoneNumber" NVARCHAR2(256) NULL, - "PhoneNumberConfirmed" NUMBER(3) NOT NULL, - "TwoFactorEnabled" NUMBER(3) NOT NULL, - "LockoutEndDateUtc" DATE NULL, - "LockoutEnabled" NUMBER(3) NOT NULL, - "AccessFailedCount" NUMBER(10) NOT NULL, - -- 追加の情報 - "ClientID" NVARCHAR2(256) NOT NULL, - "PaymentInformation" NVARCHAR2(256) NULL, - "UnstructuredData" NVARCHAR2(2000) NULL, - "FIDO2PublicKey" NVARCHAR2(2000) NULL, - "CreatedDate" DATE NOT NULL, - CONSTRAINT "PK.Users" PRIMARY KEY ("Id") -); - -CREATE TABLE "Roles"( -- Roles - "Id" NVARCHAR2(38) NOT NULL, -- PK, guid - "Name" NVARCHAR2(256) NOT NULL, - CONSTRAINT "PK.Roles" PRIMARY KEY ("Id") -); - -CREATE TABLE "UserRoles"( -- 関連エンティティ (Users *--- UserRoles ---* Roles) - "UserId" NVARCHAR2(38) NOT NULL, -- PK, guid - "RoleId" NVARCHAR2(38) NOT NULL, -- PK, guid - CONSTRAINT "PK.UserRoles" PRIMARY KEY ("UserId", "RoleId") -); - -CREATE TABLE "UserLogins"( -- Users ---* UserLogins - "UserId" NVARCHAR2(38) NOT NULL, -- PK, guid - "LoginProvider" NVARCHAR2(128) NOT NULL, -- PK - "ProviderKey" NVARCHAR2(128) NOT NULL, -- PK - CONSTRAINT "PK.UserLogins" PRIMARY KEY ("UserId", "LoginProvider", "ProviderKey") -); - -CREATE SEQUENCE TS_UserClaimID; -- TS_UserClaimID.NEXTVAL -CREATE TABLE "UserClaims"( -- Users ---* UserClaims - "Id" NUMBER(10) NOT NULL, -- PK (キー長に問題があるため"Id" "NUMBER(10)"を使用) - "UserId" NVARCHAR2(38) NOT NULL, -- *PK, guid - "Issuer" NVARCHAR2(128) NOT NULL, -- *PK(LoginProvider) *PK(実質的に複合主キー) - "ClaimType" NVARCHAR2(1024) NULL, - "ClaimValue" NVARCHAR2(1024) NULL, - CONSTRAINT "PK.UserClaims" PRIMARY KEY ("Id") -); - -CREATE TABLE "AuthenticationCodeDictionary"( - "Key" NVARCHAR2(64) NOT NULL, -- PK - "Value" NVARCHAR2(2000) NOT NULL, -- AuthenticationCode - "CreatedDate" DATE NOT NULL, - CONSTRAINT "PK.AuthCodeDictionary" PRIMARY KEY ("Key") -); - -CREATE TABLE "RefreshTokenDictionary"( - "Key" NVARCHAR2(256) NOT NULL, -- PK - "Value" RAW(1024) NOT NULL, -- RefreshToken - "CreatedDate" DATE NOT NULL, - CONSTRAINT "PK.RefreshTokenDictionary" PRIMARY KEY ("Key") -); - -CREATE TABLE "CustomizedConfirmation"( - "UserId" NVARCHAR2(38) NOT NULL, -- PK, guid - "Value" NVARCHAR2(2000) NOT NULL, -- Value - "CreatedDate" DATE NOT NULL, - CONSTRAINT "PK.CustomizedConfirmation" PRIMARY KEY ("UserId") -); - -CREATE TABLE "OAuth2Data"( -- OAuth2Data - "ClientID" NVARCHAR2(256) NOT NULL, -- PK - "UnstructuredData" NVARCHAR2(2000) NULL, -- OAuth2 Unstructured Data - CONSTRAINT "PK.OAuth2Data" PRIMARY KEY ("ClientID") -); - -CREATE TABLE "OAuth2Revocation"( - "Jti" NVARCHAR2(38) NOT NULL, -- PK, guid - "CreatedDate" DATE NOT NULL, - CONSTRAINT "PK.OAuth2Revocation" PRIMARY KEY ("Jti") -); - --- INDEX ---- UNIQUE INDEX ----- Users -CREATE UNIQUE INDEX "UserNameIndex" ON "Users" ("UserName" ASC); ---CREATE UNIQUE INDEX "ClientIDIndex" ON "Users" ("ClientID" ASC); -ALTER TABLE "Users" ADD CONSTRAINT "ClientIDIndex" UNIQUE ("ClientID"); ----- Roles -CREATE UNIQUE INDEX "RoleNameIndex" ON "Roles" ("Name" ASC); - ---- INDEX ----- UserRoles -CREATE INDEX "IX_UserRoles.UserId" ON "UserRoles" ("UserId" ASC); -CREATE INDEX "IX_UserRoles.RoleId" ON "UserRoles" ("RoleId" ASC); ----- UserLogins -CREATE INDEX "IX_UserLogins.UserId" ON "UserLogins" ("UserId" ASC); ----- UserClaims -CREATE INDEX "IX_UserClaims.UserId" ON "UserClaims" ("UserId" ASC); - --- CONSTRAINT ----- UserRoles -ALTER TABLE "UserRoles" ADD CONSTRAINT "FK.UserRoles.Users_UserId" FOREIGN KEY("UserId") REFERENCES "Users" ("Id") ON DELETE CASCADE; -ALTER TABLE "UserRoles" ADD CONSTRAINT "FK.UserRoles.Roles_RoleId" FOREIGN KEY("RoleId") REFERENCES "Roles" ("Id"); -- 使用中のRoleは削除できない。 ----- UserLogins -ALTER TABLE "UserLogins" ADD CONSTRAINT "FK.UserLogins.Users_UserId" FOREIGN KEY("UserId") REFERENCES "Users" ("Id") ON DELETE CASCADE; ----- UserClaims -ALTER TABLE "UserClaims" ADD CONSTRAINT "FK.UserClaims.Users_UserId" FOREIGN KEY("UserId") REFERENCES "Users" ("Id") ON DELETE CASCADE; ----- OAuth2Data -ALTER TABLE "OAuth2Data" ADD CONSTRAINT "FK.OAuth2Data.Users_ClientID" FOREIGN KEY("ClientID") REFERENCES "Users" ("ClientID") ON DELETE CASCADE; +-- For the information of using Oracle database and ODP.NET managed driver +-- for the user store of multi-purpose authentication site, see the following site. +-- Oracle11gXE + ODP.NET Managed Driver - マイクロソフト系技術情報 Wiki +-- https://techinfoofmicrosofttech.osscons.jp/index.php?Oracle11gXE%20%2B%20ODP.NET%20Managed%20Driver + +--UserClaimsのIDENTITY + +CREATE TABLE "Users"( -- Users + "Id" NVARCHAR2(38) NOT NULL, -- PK, guid + "UserName" NVARCHAR2(256) NOT NULL, + "Email" NVARCHAR2(256) NULL, + "EmailConfirmed" NUMBER(3) NOT NULL, + "PasswordHash" NVARCHAR2(2000) NULL, + "SecurityStamp" NVARCHAR2(2000) NULL, + "PhoneNumber" NVARCHAR2(256) NULL, + "PhoneNumberConfirmed" NUMBER(3) NOT NULL, + "TwoFactorEnabled" NUMBER(3) NOT NULL, + "LockoutEndDateUtc" TIMESTAMP NULL, + "LockoutEnabled" NUMBER(3) NOT NULL, + "AccessFailedCount" NUMBER(10) NOT NULL, + -- 追加の情報 + "ClientID" NVARCHAR2(256) NOT NULL, + "PaymentInformation" NVARCHAR2(256) NULL, + "UnstructuredData" NVARCHAR2(2000) NULL, + "FIDO2PublicKey" NVARCHAR2(2000) NULL, + "CreatedDate" TIMESTAMP NOT NULL, + "PasswordChangeDate" TIMESTAMP NOT NULL, + CONSTRAINT "PK.Users" PRIMARY KEY ("Id") +); + +CREATE TABLE "Roles"( -- Roles + "Id" NVARCHAR2(38) NOT NULL, -- PK, guid + "Name" NVARCHAR2(256) NOT NULL, + CONSTRAINT "PK.Roles" PRIMARY KEY ("Id") +); + +CREATE TABLE "UserRoles"( -- 関連エンティティ (Users *--- UserRoles ---* Roles) + "UserId" NVARCHAR2(38) NOT NULL, -- PK, guid + "RoleId" NVARCHAR2(38) NOT NULL, -- PK, guid + CONSTRAINT "PK.UserRoles" PRIMARY KEY ("UserId", "RoleId") +); + +CREATE TABLE "UserLogins"( -- Users ---* UserLogins + "UserId" NVARCHAR2(38) NOT NULL, -- PK, guid + "LoginProvider" NVARCHAR2(128) NOT NULL, -- PK + "ProviderKey" NVARCHAR2(128) NOT NULL, -- PK + CONSTRAINT "PK.UserLogins" PRIMARY KEY ("UserId", "LoginProvider", "ProviderKey") +); + +CREATE SEQUENCE TS_UserClaimID; -- TS_UserClaimID.NEXTVAL +CREATE TABLE "UserClaims"( -- Users ---* UserClaims + "Id" NUMBER(10) NOT NULL, -- PK (キー長に問題があるため"Id" "NUMBER(10)"を使用) + "UserId" NVARCHAR2(38) NOT NULL, -- *PK, guid + "Issuer" NVARCHAR2(128) NOT NULL, -- *PK(LoginProvider) *PK(実質的に複合主キー) + "ClaimType" NVARCHAR2(1024) NULL, + "ClaimValue" NVARCHAR2(1024) NULL, + CONSTRAINT "PK.UserClaims" PRIMARY KEY ("Id") +); + +CREATE TABLE "AuthenticationCodeDictionary"( + "Key" NVARCHAR2(64) NOT NULL, -- PK + "Value" NVARCHAR2(2000) NOT NULL, -- AuthenticationCode + "CreatedDate" DATE NOT NULL, + CONSTRAINT "PK.AuthCodeDictionary" PRIMARY KEY ("Key") +); + +CREATE TABLE "RefreshTokenDictionary"( + "Key" NVARCHAR2(256) NOT NULL, -- PK + "Value" RAW(1024) NOT NULL, -- RefreshToken + "CreatedDate" DATE NOT NULL, + CONSTRAINT "PK.RefreshTokenDictionary" PRIMARY KEY ("Key") +); + +CREATE TABLE "CustomizedConfirmation"( + "UserId" NVARCHAR2(38) NOT NULL, -- PK, guid + "Value" NVARCHAR2(2000) NOT NULL, -- Value + "CreatedDate" DATE NOT NULL, + CONSTRAINT "PK.CustomizedConfirmation" PRIMARY KEY ("UserId") +); + +CREATE TABLE "OAuth2Data"( -- OAuth2Data + "ClientID" NVARCHAR2(256) NOT NULL, -- PK + "UnstructuredData" NVARCHAR2(2000) NULL, -- OAuth2 Unstructured Data + CONSTRAINT "PK.OAuth2Data" PRIMARY KEY ("ClientID") +); + +CREATE TABLE "OAuth2Revocation"( + "Jti" NVARCHAR2(38) NOT NULL, -- PK, guid + "CreatedDate" DATE NOT NULL, + CONSTRAINT "PK.OAuth2Revocation" PRIMARY KEY ("Jti") +); + +-- INDEX +--- UNIQUE INDEX +---- Users +CREATE UNIQUE INDEX "UserNameIndex" ON "Users" ("UserName" ASC); +--CREATE UNIQUE INDEX "ClientIDIndex" ON "Users" ("ClientID" ASC); +ALTER TABLE "Users" ADD CONSTRAINT "ClientIDIndex" UNIQUE ("ClientID"); +---- Roles +CREATE UNIQUE INDEX "RoleNameIndex" ON "Roles" ("Name" ASC); + +--- INDEX +---- UserRoles +CREATE INDEX "IX_UserRoles.UserId" ON "UserRoles" ("UserId" ASC); +CREATE INDEX "IX_UserRoles.RoleId" ON "UserRoles" ("RoleId" ASC); +---- UserLogins +CREATE INDEX "IX_UserLogins.UserId" ON "UserLogins" ("UserId" ASC); +---- UserClaims +CREATE INDEX "IX_UserClaims.UserId" ON "UserClaims" ("UserId" ASC); + +-- CONSTRAINT +---- UserRoles +ALTER TABLE "UserRoles" ADD CONSTRAINT "FK.UserRoles.Users_UserId" FOREIGN KEY("UserId") REFERENCES "Users" ("Id") ON DELETE CASCADE; +ALTER TABLE "UserRoles" ADD CONSTRAINT "FK.UserRoles.Roles_RoleId" FOREIGN KEY("RoleId") REFERENCES "Roles" ("Id"); -- 使用中のRoleは削除できない。 +---- UserLogins +ALTER TABLE "UserLogins" ADD CONSTRAINT "FK.UserLogins.Users_UserId" FOREIGN KEY("UserId") REFERENCES "Users" ("Id") ON DELETE CASCADE; +---- UserClaims +ALTER TABLE "UserClaims" ADD CONSTRAINT "FK.UserClaims.Users_UserId" FOREIGN KEY("UserId") REFERENCES "Users" ("Id") ON DELETE CASCADE; +---- OAuth2Data +ALTER TABLE "OAuth2Data" ADD CONSTRAINT "FK.OAuth2Data.Users_ClientID" FOREIGN KEY("ClientID") REFERENCES "Users" ("ClientID") ON DELETE CASCADE; diff --git a/root/files/resource/Sql/oracle/Select_UserStore.sql b/root/files/resource/MultiPurposeAuthSite/Sql/oracle/Select_UserStore.sql similarity index 100% rename from root/files/resource/Sql/oracle/Select_UserStore.sql rename to root/files/resource/MultiPurposeAuthSite/Sql/oracle/Select_UserStore.sql diff --git a/root/files/resource/Sql/pstgrs/Create_UserStore.sql b/root/files/resource/MultiPurposeAuthSite/Sql/pstgrs/Create_UserStore.sql similarity index 99% rename from root/files/resource/Sql/pstgrs/Create_UserStore.sql rename to root/files/resource/MultiPurposeAuthSite/Sql/pstgrs/Create_UserStore.sql index 647930d6..622df4fb 100644 --- a/root/files/resource/Sql/pstgrs/Create_UserStore.sql +++ b/root/files/resource/MultiPurposeAuthSite/Sql/pstgrs/Create_UserStore.sql @@ -19,6 +19,7 @@ CREATE TABLE Users( -- Users UnstructuredData varchar(2000) NULL, FIDO2PublicKey varchar(2000) NULL, CreatedDate timestamp NOT NULL, + PasswordChangeDate timestamp NOT NULL, CONSTRAINT PK_Users PRIMARY KEY (Id) ); diff --git a/root/files/resource/Sql/pstgrs/Select_UserStore.sql b/root/files/resource/MultiPurposeAuthSite/Sql/pstgrs/Select_UserStore.sql similarity index 100% rename from root/files/resource/Sql/pstgrs/Select_UserStore.sql rename to root/files/resource/MultiPurposeAuthSite/Sql/pstgrs/Select_UserStore.sql diff --git a/root/files/resource/Sql/sqlserver/Create_UserStore.sql b/root/files/resource/MultiPurposeAuthSite/Sql/sqlserver/Create_UserStore.sql similarity index 98% rename from root/files/resource/Sql/sqlserver/Create_UserStore.sql rename to root/files/resource/MultiPurposeAuthSite/Sql/sqlserver/Create_UserStore.sql index a646132b..01bfebaf 100644 --- a/root/files/resource/Sql/sqlserver/Create_UserStore.sql +++ b/root/files/resource/MultiPurposeAuthSite/Sql/sqlserver/Create_UserStore.sql @@ -1,141 +1,142 @@ -USE [master] -GO - -IF EXISTS (select * from sysdatabases where name='UserStore') -BEGIN - ALTER DATABASE [UserStore] SET SINGLE_USER - DROP DATABASE [UserStore] -END -GO - -CREATE DATABASE [UserStore] -GO - -USE [UserStore] -GO - --- TABLE -CREATE TABLE [Users]( -- Users - [Id] [nvarchar](38) NOT NULL, -- PK, guid - [UserName] [nvarchar](256) NOT NULL, - [Email] [nvarchar](256) NULL, - [EmailConfirmed] [bit] NOT NULL, - [PasswordHash] [nvarchar](max) NULL, - [SecurityStamp] [nvarchar](max) NULL, - [PhoneNumber] [nvarchar](256) NULL, - [PhoneNumberConfirmed] [bit] NOT NULL, - [TwoFactorEnabled] [bit] NOT NULL, - [LockoutEndDateUtc] [datetime] NULL, - [LockoutEnabled] [bit] NOT NULL, - [AccessFailedCount] [int] NOT NULL, - -- 追加の情報 - [ClientID] [nvarchar](256) NOT NULL, - [PaymentInformation] [nvarchar](256) NULL, - [UnstructuredData] [nvarchar](max) NULL, - [FIDO2PublicKey] [nvarchar](max) NULL, - [CreatedDate] [smalldatetime] NOT NULL, - CONSTRAINT [PK.Users] PRIMARY KEY NONCLUSTERED ([Id] ASC) - WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] -) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] - -CREATE TABLE [Roles]( -- Roles - [Id] [nvarchar](38) NOT NULL, -- PK, guid - [Name] [nvarchar](256) NOT NULL, - CONSTRAINT [PK.Roles] PRIMARY KEY NONCLUSTERED ([Id] 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 [UserRoles]( -- 関連エンティティ (Users *--- UserRoles ---* Roles) - [UserId] [nvarchar](38) NOT NULL, -- PK, guid - [RoleId] [nvarchar](38) NOT NULL, -- PK, guid - CONSTRAINT [PK.UserRoles] PRIMARY KEY NONCLUSTERED ( - [UserId] ASC, - [RoleId] 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 [UserLogins]( -- Users ---* UserLogins - [UserId] [nvarchar](38) NOT NULL, -- PK, guid - [LoginProvider] [nvarchar](128) NOT NULL,-- PK - [ProviderKey] [nvarchar](128) NOT NULL, -- PK - CONSTRAINT [PK.UserLogins] PRIMARY KEY NONCLUSTERED ( - [UserId] ASC, - [LoginProvider] ASC, - [ProviderKey] 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 [UserClaims]( -- Users ---* UserClaims - [Id] [int] IDENTITY(1,1) NOT NULL, -- PK (キー長に問題があるため[Id] [int]を使用) - [UserId] [nvarchar](38) NOT NULL, -- *PK, guid - [Issuer] [nvarchar](128) NOT NULL, -- *PK(LoginProvider) *PK(実質的に複合主キー) - [ClaimType] [nvarchar](1024) NULL, - [ClaimValue] [nvarchar](1024) NULL, - CONSTRAINT [PK.UserClaims] PRIMARY KEY CLUSTERED ([Id] 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 [AuthenticationCodeDictionary]( - [Key] [nvarchar](64) NOT NULL, -- PK - [Value] [nvarchar](max) NOT NULL, -- AuthenticationCode - [CreatedDate] [smalldatetime] NOT NULL, - CONSTRAINT [PK.AuthenticationCodeDictionary] PRIMARY KEY NONCLUSTERED ([Key] 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 [RefreshTokenDictionary]( - [Key] [nvarchar](256) NOT NULL, -- PK - [Value] [binary](1024) NOT NULL, -- RefreshToken - [CreatedDate] [smalldatetime] NOT NULL, - CONSTRAINT [PK.RefreshTokenDictionary] PRIMARY KEY NONCLUSTERED ([Key] 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 [CustomizedConfirmation]( - [UserId] [nvarchar](38) NOT NULL, -- PK, guid - [Value] [nvarchar](max) NOT NULL, -- Value - [CreatedDate] [smalldatetime] NOT NULL, - CONSTRAINT [PK.CustomizedConfirmation] PRIMARY KEY NONCLUSTERED ([UserId] 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 [OAuth2Data]( - [ClientID] [nvarchar](256) NOT NULL, -- PK - [UnstructuredData] [nvarchar](max) NULL, -- OAuth2 Unstructured Data - CONSTRAINT [PK.OAuth2Data] PRIMARY KEY NONCLUSTERED ([ClientID] 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 [OAuth2Revocation]( - [Jti] [nvarchar](38) NOT NULL, -- PK, guid - [CreatedDate] [smalldatetime] NOT NULL, - CONSTRAINT [PK.OAuth2Revocation] 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] - - --- INDEX ----- Users -CREATE UNIQUE NONCLUSTERED INDEX [UserNameIndex] ON [Users] ([UserName] ASC) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] -CREATE UNIQUE NONCLUSTERED INDEX [ClientIDIndex] ON [Users] ([ClientID] ASC) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ----- Roles -CREATE UNIQUE NONCLUSTERED INDEX [RoleNameIndex] ON [Roles] ([Name] ASC) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ----- UserRoles -CREATE NONCLUSTERED INDEX [IX_UserRoles.UserId] ON [UserRoles] ([UserId] ASC) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] -CREATE NONCLUSTERED INDEX [IX_UserRoles.RoleId] ON [UserRoles] ([RoleId] ASC) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ----- UserLogins -CREATE NONCLUSTERED INDEX [IX_UserLogins.UserId] ON [UserLogins] ([UserId] ASC) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ----- UserClaims -CREATE NONCLUSTERED INDEX [IX_UserClaims.UserId] ON [UserClaims] ([UserId] ASC) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] - --- CONSTRAINT ----- UserRoles -ALTER TABLE [UserRoles] WITH CHECK ADD CONSTRAINT [FK.UserRoles.Users_UserId] FOREIGN KEY([UserId]) REFERENCES [Users] ([Id]) ON DELETE CASCADE -ALTER TABLE [UserRoles] WITH CHECK ADD CONSTRAINT [FK.UserRoles.Roles_RoleId] FOREIGN KEY([RoleId]) REFERENCES [Roles] ([Id]) ON DELETE NO ACTION -- 使用中のRoleは削除できない。 ----- UserLogins -ALTER TABLE [UserLogins] WITH CHECK ADD CONSTRAINT [FK.UserLogins.Users_UserId] FOREIGN KEY([UserId]) REFERENCES [Users] ([Id]) ON DELETE CASCADE ----- UserClaims ---ALTER TABLE [UserClaims] ADD CONSTRAINT [UQ.UserClaims.Users_UserId] UNIQUE ([UserId], [ClaimType], [ClaimValue]) -- キー長の問題でダメ。 -ALTER TABLE [UserClaims] WITH CHECK ADD CONSTRAINT [FK.UserClaims.Users_UserId] FOREIGN KEY([UserId]) REFERENCES [Users] ([Id]) ON DELETE CASCADE ----- OAuth2Data -ALTER TABLE [OAuth2Data] WITH CHECK ADD CONSTRAINT [FK.OAuth2Data.Users_ClientID] FOREIGN KEY([ClientID]) REFERENCES [Users] ([ClientID]) ON DELETE CASCADE +USE [master] +GO + +IF EXISTS (select * from sysdatabases where name='UserStore') +BEGIN + ALTER DATABASE [UserStore] SET SINGLE_USER + DROP DATABASE [UserStore] +END +GO + +CREATE DATABASE [UserStore] +GO + +USE [UserStore] +GO + +-- TABLE +CREATE TABLE [Users]( -- Users + [Id] [nvarchar](38) NOT NULL, -- PK, guid + [UserName] [nvarchar](256) NOT NULL, + [Email] [nvarchar](256) NULL, + [EmailConfirmed] [bit] NOT NULL, + [PasswordHash] [nvarchar](max) NULL, + [SecurityStamp] [nvarchar](max) NULL, + [PhoneNumber] [nvarchar](256) NULL, + [PhoneNumberConfirmed] [bit] NOT NULL, + [TwoFactorEnabled] [bit] NOT NULL, + [LockoutEndDateUtc] [datetime] NULL, + [LockoutEnabled] [bit] NOT NULL, + [AccessFailedCount] [int] NOT NULL, + -- 追加の情報 + [ClientID] [nvarchar](256) NOT NULL, + [PaymentInformation] [nvarchar](256) NULL, + [UnstructuredData] [nvarchar](max) NULL, + [FIDO2PublicKey] [nvarchar](max) NULL, + [CreatedDate] [smalldatetime] NOT NULL, + [PasswordChangeDate] [smalldatetime] NOT NULL, + CONSTRAINT [PK.Users] PRIMARY KEY NONCLUSTERED ([Id] ASC) + WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] +) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] + +CREATE TABLE [Roles]( -- Roles + [Id] [nvarchar](38) NOT NULL, -- PK, guid + [Name] [nvarchar](256) NOT NULL, + CONSTRAINT [PK.Roles] PRIMARY KEY NONCLUSTERED ([Id] 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 [UserRoles]( -- 関連エンティティ (Users *--- UserRoles ---* Roles) + [UserId] [nvarchar](38) NOT NULL, -- PK, guid + [RoleId] [nvarchar](38) NOT NULL, -- PK, guid + CONSTRAINT [PK.UserRoles] PRIMARY KEY NONCLUSTERED ( + [UserId] ASC, + [RoleId] 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 [UserLogins]( -- Users ---* UserLogins + [UserId] [nvarchar](38) NOT NULL, -- PK, guid + [LoginProvider] [nvarchar](128) NOT NULL,-- PK + [ProviderKey] [nvarchar](128) NOT NULL, -- PK + CONSTRAINT [PK.UserLogins] PRIMARY KEY NONCLUSTERED ( + [UserId] ASC, + [LoginProvider] ASC, + [ProviderKey] 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 [UserClaims]( -- Users ---* UserClaims + [Id] [int] IDENTITY(1,1) NOT NULL, -- PK (キー長に問題があるため[Id] [int]を使用) + [UserId] [nvarchar](38) NOT NULL, -- *PK, guid + [Issuer] [nvarchar](128) NOT NULL, -- *PK(LoginProvider) *PK(実質的に複合主キー) + [ClaimType] [nvarchar](1024) NULL, + [ClaimValue] [nvarchar](1024) NULL, + CONSTRAINT [PK.UserClaims] PRIMARY KEY CLUSTERED ([Id] 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 [AuthenticationCodeDictionary]( + [Key] [nvarchar](64) NOT NULL, -- PK + [Value] [nvarchar](max) NOT NULL, -- AuthenticationCode + [CreatedDate] [smalldatetime] NOT NULL, + CONSTRAINT [PK.AuthenticationCodeDictionary] PRIMARY KEY NONCLUSTERED ([Key] 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 [RefreshTokenDictionary]( + [Key] [nvarchar](256) NOT NULL, -- PK + [Value] [binary](1024) NOT NULL, -- RefreshToken + [CreatedDate] [smalldatetime] NOT NULL, + CONSTRAINT [PK.RefreshTokenDictionary] PRIMARY KEY NONCLUSTERED ([Key] 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 [CustomizedConfirmation]( + [UserId] [nvarchar](38) NOT NULL, -- PK, guid + [Value] [nvarchar](max) NOT NULL, -- Value + [CreatedDate] [smalldatetime] NOT NULL, + CONSTRAINT [PK.CustomizedConfirmation] PRIMARY KEY NONCLUSTERED ([UserId] 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 [OAuth2Data]( + [ClientID] [nvarchar](256) NOT NULL, -- PK + [UnstructuredData] [nvarchar](max) NULL, -- OAuth2 Unstructured Data + CONSTRAINT [PK.OAuth2Data] PRIMARY KEY NONCLUSTERED ([ClientID] 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 [OAuth2Revocation]( + [Jti] [nvarchar](38) NOT NULL, -- PK, guid + [CreatedDate] [smalldatetime] NOT NULL, + CONSTRAINT [PK.OAuth2Revocation] 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] + + +-- INDEX +---- Users +CREATE UNIQUE NONCLUSTERED INDEX [UserNameIndex] ON [Users] ([UserName] ASC) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] +CREATE UNIQUE NONCLUSTERED INDEX [ClientIDIndex] ON [Users] ([ClientID] ASC) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] +---- Roles +CREATE UNIQUE NONCLUSTERED INDEX [RoleNameIndex] ON [Roles] ([Name] ASC) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] +---- UserRoles +CREATE NONCLUSTERED INDEX [IX_UserRoles.UserId] ON [UserRoles] ([UserId] ASC) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] +CREATE NONCLUSTERED INDEX [IX_UserRoles.RoleId] ON [UserRoles] ([RoleId] ASC) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] +---- UserLogins +CREATE NONCLUSTERED INDEX [IX_UserLogins.UserId] ON [UserLogins] ([UserId] ASC) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] +---- UserClaims +CREATE NONCLUSTERED INDEX [IX_UserClaims.UserId] ON [UserClaims] ([UserId] ASC) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] + +-- CONSTRAINT +---- UserRoles +ALTER TABLE [UserRoles] WITH CHECK ADD CONSTRAINT [FK.UserRoles.Users_UserId] FOREIGN KEY([UserId]) REFERENCES [Users] ([Id]) ON DELETE CASCADE +ALTER TABLE [UserRoles] WITH CHECK ADD CONSTRAINT [FK.UserRoles.Roles_RoleId] FOREIGN KEY([RoleId]) REFERENCES [Roles] ([Id]) ON DELETE NO ACTION -- 使用中のRoleは削除できない。 +---- UserLogins +ALTER TABLE [UserLogins] WITH CHECK ADD CONSTRAINT [FK.UserLogins.Users_UserId] FOREIGN KEY([UserId]) REFERENCES [Users] ([Id]) ON DELETE CASCADE +---- UserClaims +--ALTER TABLE [UserClaims] ADD CONSTRAINT [UQ.UserClaims.Users_UserId] UNIQUE ([UserId], [ClaimType], [ClaimValue]) -- キー長の問題でダメ。 +ALTER TABLE [UserClaims] WITH CHECK ADD CONSTRAINT [FK.UserClaims.Users_UserId] FOREIGN KEY([UserId]) REFERENCES [Users] ([Id]) ON DELETE CASCADE +---- OAuth2Data +ALTER TABLE [OAuth2Data] WITH CHECK ADD CONSTRAINT [FK.OAuth2Data.Users_ClientID] FOREIGN KEY([ClientID]) REFERENCES [Users] ([ClientID]) ON DELETE CASCADE diff --git a/root/files/resource/Sql/sqlserver/Select_UserStore.sql b/root/files/resource/MultiPurposeAuthSite/Sql/sqlserver/Select_UserStore.sql similarity index 100% rename from root/files/resource/Sql/sqlserver/Select_UserStore.sql rename to root/files/resource/MultiPurposeAuthSite/Sql/sqlserver/Select_UserStore.sql diff --git a/root/files/resource/Txt/AccountChangeWasCompletedEmailMsg.ja.txt b/root/files/resource/MultiPurposeAuthSite/Txt/AccountChangeWasCompletedEmailMsg.ja.txt similarity index 100% rename from root/files/resource/Txt/AccountChangeWasCompletedEmailMsg.ja.txt rename to root/files/resource/MultiPurposeAuthSite/Txt/AccountChangeWasCompletedEmailMsg.ja.txt diff --git a/root/files/resource/Txt/AccountChangeWasCompletedEmailMsg.txt b/root/files/resource/MultiPurposeAuthSite/Txt/AccountChangeWasCompletedEmailMsg.txt similarity index 100% rename from root/files/resource/Txt/AccountChangeWasCompletedEmailMsg.txt rename to root/files/resource/MultiPurposeAuthSite/Txt/AccountChangeWasCompletedEmailMsg.txt diff --git a/root/files/resource/Txt/AccountChangeWasCompletedEmailTitle.ja.txt b/root/files/resource/MultiPurposeAuthSite/Txt/AccountChangeWasCompletedEmailTitle.ja.txt similarity index 100% rename from root/files/resource/Txt/AccountChangeWasCompletedEmailTitle.ja.txt rename to root/files/resource/MultiPurposeAuthSite/Txt/AccountChangeWasCompletedEmailTitle.ja.txt diff --git a/root/files/resource/Txt/AccountChangeWasCompletedEmailTitle.txt b/root/files/resource/MultiPurposeAuthSite/Txt/AccountChangeWasCompletedEmailTitle.txt similarity index 100% rename from root/files/resource/Txt/AccountChangeWasCompletedEmailTitle.txt rename to root/files/resource/MultiPurposeAuthSite/Txt/AccountChangeWasCompletedEmailTitle.txt diff --git a/root/files/resource/Txt/AddPhoneNumber.ja.txt b/root/files/resource/MultiPurposeAuthSite/Txt/AddPhoneNumber.ja.txt similarity index 100% rename from root/files/resource/Txt/AddPhoneNumber.ja.txt rename to root/files/resource/MultiPurposeAuthSite/Txt/AddPhoneNumber.ja.txt diff --git a/root/files/resource/Txt/AddPhoneNumber.txt b/root/files/resource/MultiPurposeAuthSite/Txt/AddPhoneNumber.txt similarity index 100% rename from root/files/resource/Txt/AddPhoneNumber.txt rename to root/files/resource/MultiPurposeAuthSite/Txt/AddPhoneNumber.txt diff --git a/root/files/resource/Txt/Agreement.ja.txt b/root/files/resource/MultiPurposeAuthSite/Txt/Agreement.ja.txt similarity index 100% rename from root/files/resource/Txt/Agreement.ja.txt rename to root/files/resource/MultiPurposeAuthSite/Txt/Agreement.ja.txt diff --git a/root/files/resource/Txt/Agreement.txt b/root/files/resource/MultiPurposeAuthSite/Txt/Agreement.txt similarity index 100% rename from root/files/resource/Txt/Agreement.txt rename to root/files/resource/MultiPurposeAuthSite/Txt/Agreement.txt diff --git a/root/files/resource/Txt/EmailConfirmationMsg.ja.txt b/root/files/resource/MultiPurposeAuthSite/Txt/EmailConfirmationMsg.ja.txt similarity index 100% rename from root/files/resource/Txt/EmailConfirmationMsg.ja.txt rename to root/files/resource/MultiPurposeAuthSite/Txt/EmailConfirmationMsg.ja.txt diff --git a/root/files/resource/Txt/EmailConfirmationMsg.txt b/root/files/resource/MultiPurposeAuthSite/Txt/EmailConfirmationMsg.txt similarity index 100% rename from root/files/resource/Txt/EmailConfirmationMsg.txt rename to root/files/resource/MultiPurposeAuthSite/Txt/EmailConfirmationMsg.txt diff --git a/root/files/resource/Txt/EmailConfirmationTitle.ja.txt b/root/files/resource/MultiPurposeAuthSite/Txt/EmailConfirmationTitle.ja.txt similarity index 100% rename from root/files/resource/Txt/EmailConfirmationTitle.ja.txt rename to root/files/resource/MultiPurposeAuthSite/Txt/EmailConfirmationTitle.ja.txt diff --git a/root/files/resource/Txt/EmailConfirmationTitle.txt b/root/files/resource/MultiPurposeAuthSite/Txt/EmailConfirmationTitle.txt similarity index 100% rename from root/files/resource/Txt/EmailConfirmationTitle.txt rename to root/files/resource/MultiPurposeAuthSite/Txt/EmailConfirmationTitle.txt diff --git a/root/files/resource/Txt/PasswordResetMsg.ja.txt b/root/files/resource/MultiPurposeAuthSite/Txt/PasswordResetMsg.ja.txt similarity index 100% rename from root/files/resource/Txt/PasswordResetMsg.ja.txt rename to root/files/resource/MultiPurposeAuthSite/Txt/PasswordResetMsg.ja.txt diff --git a/root/files/resource/Txt/PasswordResetMsg.txt b/root/files/resource/MultiPurposeAuthSite/Txt/PasswordResetMsg.txt similarity index 100% rename from root/files/resource/Txt/PasswordResetMsg.txt rename to root/files/resource/MultiPurposeAuthSite/Txt/PasswordResetMsg.txt diff --git a/root/files/resource/Txt/PasswordResetTitle.ja.txt b/root/files/resource/MultiPurposeAuthSite/Txt/PasswordResetTitle.ja.txt similarity index 100% rename from root/files/resource/Txt/PasswordResetTitle.ja.txt rename to root/files/resource/MultiPurposeAuthSite/Txt/PasswordResetTitle.ja.txt diff --git a/root/files/resource/Txt/PasswordResetTitle.txt b/root/files/resource/MultiPurposeAuthSite/Txt/PasswordResetTitle.txt similarity index 100% rename from root/files/resource/Txt/PasswordResetTitle.txt rename to root/files/resource/MultiPurposeAuthSite/Txt/PasswordResetTitle.txt diff --git a/root/files/resource/Txt/PasswordResetWasCompletedEmailMsg.ja.txt b/root/files/resource/MultiPurposeAuthSite/Txt/PasswordResetWasCompletedEmailMsg.ja.txt similarity index 100% rename from root/files/resource/Txt/PasswordResetWasCompletedEmailMsg.ja.txt rename to root/files/resource/MultiPurposeAuthSite/Txt/PasswordResetWasCompletedEmailMsg.ja.txt diff --git a/root/files/resource/Txt/PasswordResetWasCompletedEmailMsg.txt b/root/files/resource/MultiPurposeAuthSite/Txt/PasswordResetWasCompletedEmailMsg.txt similarity index 100% rename from root/files/resource/Txt/PasswordResetWasCompletedEmailMsg.txt rename to root/files/resource/MultiPurposeAuthSite/Txt/PasswordResetWasCompletedEmailMsg.txt diff --git a/root/files/resource/Txt/PasswordResetWasCompletedEmailTitle.ja.txt b/root/files/resource/MultiPurposeAuthSite/Txt/PasswordResetWasCompletedEmailTitle.ja.txt similarity index 100% rename from root/files/resource/Txt/PasswordResetWasCompletedEmailTitle.ja.txt rename to root/files/resource/MultiPurposeAuthSite/Txt/PasswordResetWasCompletedEmailTitle.ja.txt diff --git a/root/files/resource/Txt/PasswordResetWasCompletedEmailTitle.txt b/root/files/resource/MultiPurposeAuthSite/Txt/PasswordResetWasCompletedEmailTitle.txt similarity index 100% rename from root/files/resource/Txt/PasswordResetWasCompletedEmailTitle.txt rename to root/files/resource/MultiPurposeAuthSite/Txt/PasswordResetWasCompletedEmailTitle.txt diff --git a/root/files/resource/Txt/RegistationWasCompletedEmailMsg.ja.txt b/root/files/resource/MultiPurposeAuthSite/Txt/RegistationWasCompletedEmailMsg.ja.txt similarity index 100% rename from root/files/resource/Txt/RegistationWasCompletedEmailMsg.ja.txt rename to root/files/resource/MultiPurposeAuthSite/Txt/RegistationWasCompletedEmailMsg.ja.txt diff --git a/root/files/resource/Txt/RegistationWasCompletedEmailMsg.txt b/root/files/resource/MultiPurposeAuthSite/Txt/RegistationWasCompletedEmailMsg.txt similarity index 100% rename from root/files/resource/Txt/RegistationWasCompletedEmailMsg.txt rename to root/files/resource/MultiPurposeAuthSite/Txt/RegistationWasCompletedEmailMsg.txt diff --git a/root/files/resource/Txt/RegistationWasCompletedEmailTitle.ja.txt b/root/files/resource/MultiPurposeAuthSite/Txt/RegistationWasCompletedEmailTitle.ja.txt similarity index 100% rename from root/files/resource/Txt/RegistationWasCompletedEmailTitle.ja.txt rename to root/files/resource/MultiPurposeAuthSite/Txt/RegistationWasCompletedEmailTitle.ja.txt diff --git a/root/files/resource/Txt/RegistationWasCompletedEmailTitle.txt b/root/files/resource/MultiPurposeAuthSite/Txt/RegistationWasCompletedEmailTitle.txt similarity index 100% rename from root/files/resource/Txt/RegistationWasCompletedEmailTitle.txt rename to root/files/resource/MultiPurposeAuthSite/Txt/RegistationWasCompletedEmailTitle.txt diff --git a/root/files/resource/Xml/MSGDefinition.xml b/root/files/resource/MultiPurposeAuthSite/Xml/MSGDefinition.xml similarity index 100% rename from root/files/resource/Xml/MSGDefinition.xml rename to root/files/resource/MultiPurposeAuthSite/Xml/MSGDefinition.xml diff --git a/root/files/resource/Xml/MSGDefinition_ja.xml b/root/files/resource/MultiPurposeAuthSite/Xml/MSGDefinition_ja.xml similarity index 100% rename from root/files/resource/Xml/MSGDefinition_ja.xml rename to root/files/resource/MultiPurposeAuthSite/Xml/MSGDefinition_ja.xml diff --git a/root/files/resource/Xml/MSGDefinition_zh-CN.xml b/root/files/resource/MultiPurposeAuthSite/Xml/MSGDefinition_zh-CN.xml similarity index 100% rename from root/files/resource/Xml/MSGDefinition_zh-CN.xml rename to root/files/resource/MultiPurposeAuthSite/Xml/MSGDefinition_zh-CN.xml diff --git a/root/files/resource/Xml/SPDefinition.xml b/root/files/resource/MultiPurposeAuthSite/Xml/SPDefinition.xml similarity index 100% rename from root/files/resource/Xml/SPDefinition.xml rename to root/files/resource/MultiPurposeAuthSite/Xml/SPDefinition.xml diff --git a/root/files/resource/Xml/SCDefinition.xml b/root/files/resource/Xml/SCDefinition.xml deleted file mode 100644 index cf3438e4..00000000 --- a/root/files/resource/Xml/SCDefinition.xml +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - -]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/root/files/resource/Xml/TCDefinition.xml b/root/files/resource/Xml/TCDefinition.xml deleted file mode 100644 index 4193d412..00000000 --- a/root/files/resource/Xml/TCDefinition.xml +++ /dev/null @@ -1,75 +0,0 @@ - - - - - - -]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/root/files/resource/Xml/TMInProcessDefinition.xml b/root/files/resource/Xml/TMInProcessDefinition.xml deleted file mode 100644 index f01b0112..00000000 --- a/root/files/resource/Xml/TMInProcessDefinition.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - -]> - - - - - - - - - - - - - \ No newline at end of file diff --git a/root/files/resource/Xml/TMProtocolDefinition.xml b/root/files/resource/Xml/TMProtocolDefinition.xml deleted file mode 100644 index 3e753fab..00000000 --- a/root/files/resource/Xml/TMProtocolDefinition.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - -]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/root/files/resource/Xml/TMProtocolDefinition2.xml b/root/files/resource/Xml/TMProtocolDefinition2.xml deleted file mode 100644 index 175566cc..00000000 --- a/root/files/resource/Xml/TMProtocolDefinition2.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - -]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/root/programs/10_MultiPurposeAuthSite.bat b/root/programs/10_MultiPurposeAuthSite.bat index 397f7dcb..2d68075b 100644 --- a/root/programs/10_MultiPurposeAuthSite.bat +++ b/root/programs/10_MultiPurposeAuthSite.bat @@ -18,8 +18,8 @@ call %CURRENT_DIR%z_Common.bat rem -------------------------------------------------- rem Batch build of MultiPurposeAuthSite. rem -------------------------------------------------- -nuget.exe restore "MultiPurposeAuthSite\MultiPurposeAuthSite.sln" -%BUILDFILEPATH% %COMMANDLINE% "MultiPurposeAuthSite\MultiPurposeAuthSite.sln" +nuget.exe restore "MultiPurposeAuthSite\MultiPurposeAuthSiteAll.sln" +%BUILDFILEPATH% %COMMANDLINE% "MultiPurposeAuthSite\MultiPurposeAuthSiteAll.sln" pause diff --git a/root/programs/1_DeleteDir.bat b/root/programs/1_DeleteDir.bat index f65bbb07..634324d7 100644 --- a/root/programs/1_DeleteDir.bat +++ b/root/programs/1_DeleteDir.bat @@ -1,15 +1,21 @@ @echo off @echo -------------------------------------------------- -@echo Delete the obj, bin, Temp, Build, PrecompiledWeb folders. +@echo Delete the packages, obj, bin, bld, Temp, Build, PrecompiledWeb, .vs folders. @echo -------------------------------------------------- +for /D /R %%i in ( packages ) do ( + if exist "%%~i" RD /S /Q "%%~i" +) for /D /R %%i in ( obj ) do ( if exist "%%~i" RD /S /Q "%%~i" ) for /D /R %%i in ( bin ) do ( if exist "%%~i" RD /S /Q "%%~i" ) +for /D /R %%i in ( bld ) do ( + if exist "%%~i" RD /S /Q "%%~i" +) for /D /R %%i in ( Temp ) do ( if exist "%%~i" RD /S /Q "%%~i" ) @@ -19,12 +25,7 @@ for /D /R %%i in ( Build ) do ( for /D /R %%i in ( PrecompiledWeb ) do ( if exist "%%~i" RD /S /Q "%%~i" ) -for /D /R %%i in ( packages ) do ( +for /D /R %%i in ( .vs ) do ( if exist "%%~i" RD /S /Q "%%~i" ) - -@echo -------------------------------------------------- -@echo Deleted the obj, bin, Temp, Build, PrecompiledWeb folders. -@echo -------------------------------------------------- - pause diff --git a/root/programs/2_DeleteFile.bat b/root/programs/2_DeleteFile.bat index d1296355..26222e30 100644 --- a/root/programs/2_DeleteFile.bat +++ b/root/programs/2_DeleteFile.bat @@ -1,13 +1,15 @@ @echo off +SET EXTENTION=*.suo *.user *.tmp *.log *.bak *.skrold + @echo -------------------------------------------------- -@echo Delete the suo *.user *.tmp *.bak *.log files. +@echo Delete the %EXTENTION%. @echo -------------------------------------------------- -del /f /s /a- *.suo *.user *.tmp *.bak *.log +del /f /s /a- %EXTENTION% @echo -------------------------------------------------- -@echo Deleted the suo *.user *.tmp *.bak *.log files. +@echo Deleted the %EXTENTION%. @echo -------------------------------------------------- -pause \ No newline at end of file +pause diff --git a/root/programs/3_Build_NetCore.bat b/root/programs/3_Build_NetCore.bat new file mode 100644 index 00000000..7d04247d --- /dev/null +++ b/root/programs/3_Build_NetCore.bat @@ -0,0 +1,27 @@ +setlocal + +@rem -------------------------------------------------- +@rem Turn off the echo function. +@rem -------------------------------------------------- +@echo off + +@rem -------------------------------------------------- +@rem Get the path to the executable file. +@rem -------------------------------------------------- +set CURRENT_DIR="%~dp0" + +@rem -------------------------------------------------- +@rem Execution of the common processing. +@rem -------------------------------------------------- +call %CURRENT_DIR%z_Common.bat + +rem -------------------------------------------------- +rem Build the batch Infrastructure +rem -------------------------------------------------- +dotnet restore "Frameworks\Infrastructure\AllComponent_netcore.sln" +dotnet msbuild %COMMANDLINE% "Frameworks\Infrastructure\AllComponent_netcore.sln" + +pause + +rem ------------------------------------------------------- +endlocal \ No newline at end of file diff --git a/root/programs/Frameworks/Infrastructure/AllComponent_netcore.sln b/root/programs/Frameworks/Infrastructure/AllComponent_netcore.sln new file mode 100644 index 00000000..497d9655 --- /dev/null +++ b/root/programs/Frameworks/Infrastructure/AllComponent_netcore.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.27428.2015 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Business_netcore20", "Business\Business_netcore20.csproj", "{87C03805-26A4-452B-97C7-2C8598722DDE}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {87C03805-26A4-452B-97C7-2C8598722DDE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {87C03805-26A4-452B-97C7-2C8598722DDE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {87C03805-26A4-452B-97C7-2C8598722DDE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {87C03805-26A4-452B-97C7-2C8598722DDE}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {2FF75561-B8E7-4F22-A5F7-E967511FD51B} + EndGlobalSection +EndGlobal diff --git a/root/programs/Frameworks/Infrastructure/Business/AsyncProcessingService/AsyncProcessingServiceParameterValue.cs b/root/programs/Frameworks/Infrastructure/Business/AsyncProcessingService/AsyncProcessingServiceParameterValue.cs deleted file mode 100644 index d18d6bdf..00000000 --- a/root/programs/Frameworks/Infrastructure/Business/AsyncProcessingService/AsyncProcessingServiceParameterValue.cs +++ /dev/null @@ -1,194 +0,0 @@ -//********************************************************************************** -//* Copyright (C) 2007,2016 Hitachi Solutions,Ltd. -//********************************************************************************** - -#region Apache License -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#endregion - -//********************************************************************************** -//* クラス名 :AsyncProcessingServiceParameterValue -//* クラス日本語名 :AsyncProcessingServiceParameterValue -//* -//* 日時 更新者 内容 -//* ---------- ---------------- ------------------------------------------------- -//* 11/28/2014 Supragyan Paramter Value class for Asynchronous Processing Service -//* 04/15/2015 Sandeep Changed datatype of ProgressRate to decimal. -//********************************************************************************** - -using System; -using System.Reflection; - -using Touryo.Infrastructure.Business.Common; -using Touryo.Infrastructure.Business.Util; - -namespace Touryo.Infrastructure.Business.AsyncProcessingService -{ - /// - /// Paramter Value class for Asynchronous Processing Service - /// - public class AsyncProcessingServiceParameterValue : MyParameterValue - { - /// 汎用エリア - public object Obj; - - /// TaskId - public int TaskId; - - /// UserId - public string UserId; - - /// ProcessName - public string ProcessName; - - /// Data - public string Data; - - /// RegistrationDateTime - public DateTime RegistrationDateTime; - - /// ExecutionStartDateTime - public DateTime ExecutionStartDateTime; - - /// NumberOfRetries - public int NumberOfRetries; - - /// ProgressRate - public decimal ProgressRate; - - /// Status - public int StatusId; - - /// CompletionDateTime - public DateTime CompletionDateTime; - - /// CommandId - public int CommandId; - - /// ReservedArea - public string ReservedArea; - - /// ExceptionInfo - public string ExceptionInfo; - - #region コンストラクタ - - /// コンストラクタ - public AsyncProcessingServiceParameterValue(string screenId, string controlId, string methodName, string actionType, MyUserInfo user) - : base(screenId, controlId, methodName, actionType, user) - { - // Baseのコンストラクタに引数を渡すために必要。 - } - - #endregion - - #region AsyncStatus - - /// - /// AsyncStatus Enum for storing all status - /// - public enum AsyncStatus - { - /// Register - [StringValue("Register")] - Register = 1, - - /// Processing - [StringValue("Processing")] - Processing, - - /// End - [StringValue("End")] - End, - - /// AbnormalEnd - [StringValue("AbnormalEnd")] - AbnormalEnd, - - /// Abort - [StringValue("Abort")] - Abort, - } - - #endregion - - #region AsyncCommand - - /// - /// AsyncCommand Enum for storing command values - /// - public enum AsyncCommand - { - /// Stop - [StringValue("Stop")] - Stop = 1, - - /// Abort - [StringValue("Abort")] - Abort, - } - - #endregion - } - - /// - /// To get the string value - /// - public class StringValueAttribute : System.Attribute - { - private string _value; - - /// StringValueAttribute - /// value - public StringValueAttribute(string value) - { - _value = value; - } - - /// Value - public string Value - { - get { return _value; } - } - } - - /// - /// Class that holds the Enum values string - /// - public class StringEnum - { - /// - /// To get the string value from Enum value - /// - /// Enum value - /// String value of Enum - public static string GetStringValue(Enum value) - { - string output = null; - Type type = value.GetType(); - - // Gets the 'StringValueAttribute' - FieldInfo fi = type.GetField(value.ToString()); - StringValueAttribute[] attrs = - fi.GetCustomAttributes(typeof(StringValueAttribute), - false) as StringValueAttribute[]; - if (attrs.Length > 0) - { - output = attrs[0].Value; - } - return output; - } - } -} diff --git a/root/programs/Frameworks/Infrastructure/Business/AsyncProcessingService/AsyncProcessingServiceReturnValue.cs b/root/programs/Frameworks/Infrastructure/Business/AsyncProcessingService/AsyncProcessingServiceReturnValue.cs deleted file mode 100644 index cfd6ae2e..00000000 --- a/root/programs/Frameworks/Infrastructure/Business/AsyncProcessingService/AsyncProcessingServiceReturnValue.cs +++ /dev/null @@ -1,85 +0,0 @@ -//********************************************************************************** -//* Copyright (C) 2007,2016 Hitachi Solutions,Ltd. -//********************************************************************************** - -#region Apache License -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#endregion - -//********************************************************************************** -//* クラス名 :AsyncProcessingServiceReturnValue -//* クラス日本語名 :AsyncProcessingServiceReturnValue -//* -//* 日時 更新者 内容 -//* ---------- ---------------- ------------------------------------------------- -//* 11/28/2014 Supragyan Paramter Return Value class for Asynchronous Processing Service -//* 04/15/2015 Sandeep Changed datatype of ProgressRate to decimal. -//********************************************************************************** - -using System; -using Touryo.Infrastructure.Business.Common; - -namespace Touryo.Infrastructure.Business.AsyncProcessingService -{ - - /// - /// Paramter Return Value class for Asynchronous Processing Service - /// - public class AsyncProcessingServiceReturnValue : MyReturnValue - { - /// 汎用エリア - public object Obj; - - /// TaskId - public int TaskId; - - /// UserId - public string UserId; - - /// ProcessName - public string ProcessName; - - /// Data - public string Data; - - /// RegistrationDateTime - public DateTime RegistrationDateTime; - - /// ExecutionStartDateTime; - public DateTime ExecutionStartDateTime; - - /// NumberOfRetries; - public int NumberOfRetries; - - /// ProgressRate - public decimal ProgressRate; - - /// StatusId; - public int StatusId; - - /// CompletionDateTime - public DateTime CompletionDateTime; - - /// CommandId; - public int CommandId; - - /// ReservedArea - public string ReservedArea; - - /// ExceptionInfo - public string ExceptionInfo; - } - -} diff --git a/root/programs/Frameworks/Infrastructure/Business/AsyncProcessingService/LayerB.cs b/root/programs/Frameworks/Infrastructure/Business/AsyncProcessingService/LayerB.cs deleted file mode 100644 index 4afc7e0e..00000000 --- a/root/programs/Frameworks/Infrastructure/Business/AsyncProcessingService/LayerB.cs +++ /dev/null @@ -1,262 +0,0 @@ -//********************************************************************************** -//* Copyright (C) 2007,2016 Hitachi Solutions,Ltd. -//********************************************************************************** - -#region Apache License -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#endregion - -//********************************************************************************** -//* クラス名 :LayerB -//* クラス日本語名 :LayerB -//* -//* 日時 更新者 内容 -//* ---------- ---------------- ------------------------------------------------- -//* 11/28/2014 Supragyan Created LayerB class for AsyncProcessing Service -//* 11/28/2014 Supragyan Created Insert,Update,Select method for AsyncProcessing Service -//* 04/15/2015 Sandeep Did code modification of insert, update and select for AsyncProcessing Service -//* 06/09/2015 Sandeep Implemented code to update stop command to all the running asynchronous task -//* Modified code to reset Exception information, before starting asynchronous task -//* 06/26/2015 Sandeep Implemented code to get commandID in the SelectTask method, -//* to resolve unstable "Register" state, when you invoke [Abort] to AsyncTask, at this "Register" state -//* 06/01/2016 Sandeep Implemented method to test the connection of specified database -//********************************************************************************** - -using System; -using System.Data; - -using Touryo.Infrastructure.Business.Business; - -namespace Touryo.Infrastructure.Business.AsyncProcessingService -{ - #region LayerB - - /// - /// LayerB class for AsyncProcessing Service - /// - public class LayerB : MyFcBaseLogic - { - #region Insert - - /// - /// Inserts Async Parameter values to Database through LayerD - /// - /// - public void UOC_InsertTask(AsyncProcessingServiceParameterValue asyncParameterValue) - { - // 戻り値クラスを生成して、事前に戻り値に設定しておく。 - AsyncProcessingServiceReturnValue asyncReturnValue = new AsyncProcessingServiceReturnValue(); - this.ReturnValue = asyncReturnValue; - - LayerD myDao = new LayerD(this.GetDam()); - myDao.InsertTask(asyncParameterValue, asyncReturnValue); - } - - #endregion - - #region Update - - #region UpdateTaskStart - - /// - /// Updates information in the database that the asynchronous task is started - /// - /// Asynchronous Parameter Values - private void UOC_UpdateTaskStart(AsyncProcessingServiceParameterValue asyncParameterValue) - { - AsyncProcessingServiceReturnValue asyncReturnValue = new AsyncProcessingServiceReturnValue(); - this.ReturnValue = asyncReturnValue; - - LayerD myDao = new LayerD(this.GetDam()); - myDao.UpdateTaskStart(asyncParameterValue, asyncReturnValue); - } - - #endregion - - #region UpdateTaskRetry - - /// - /// Updates information in the database that the asynchronous task is failed and can be retried later - /// - /// Asynchronous Parameter Values - private void UOC_UpdateTaskRetry(AsyncProcessingServiceParameterValue asyncParameterValue) - { - AsyncProcessingServiceReturnValue asyncReturnValue = new AsyncProcessingServiceReturnValue(); - this.ReturnValue = asyncReturnValue; - - LayerD myDao = new LayerD(this.GetDam()); - myDao.UpdateTaskRetry(asyncParameterValue, asyncReturnValue); - } - - #endregion - - #region UpdateTaskFail - - /// - /// Updates information in the database that the asynchronous task is failed and abort this task [status=Abort] - /// - /// Asynchronous Parameter Values - private void UOC_UpdateTaskFail(AsyncProcessingServiceParameterValue asyncParameterValue) - { - AsyncProcessingServiceReturnValue asyncReturnValue = new AsyncProcessingServiceReturnValue(); - this.ReturnValue = asyncReturnValue; - - LayerD myDao = new LayerD(this.GetDam()); - myDao.UpdateTaskFail(asyncParameterValue, asyncReturnValue); - } - - #endregion - - #region UpdateTaskSuccess - - /// - /// Updates information in the database that the asynchronous task is completed - /// - /// Asynchronous Parameter Values - private void UOC_UpdateTaskSuccess(AsyncProcessingServiceParameterValue asyncParameterValue) - { - AsyncProcessingServiceReturnValue asyncReturnValue = new AsyncProcessingServiceReturnValue(); - this.ReturnValue = asyncReturnValue; - - LayerD myDao = new LayerD(this.GetDam()); - myDao.UpdateTaskSuccess(asyncParameterValue, asyncReturnValue); - } - - #endregion - - #region UpdateTaskProgress - - /// - /// Updates progress rate of the asynchronous task in the database. - /// - /// Asynchronous Parameter Values - private void UOC_UpdateTaskProgress(AsyncProcessingServiceParameterValue asyncParameterValue) - { - AsyncProcessingServiceReturnValue asyncReturnValue = new AsyncProcessingServiceReturnValue(); - this.ReturnValue = asyncReturnValue; - - LayerD myDao = new LayerD(this.GetDam()); - myDao.UpdateTaskProgress(asyncParameterValue, asyncReturnValue); - } - - #endregion - - #region UpdateTaskCommand - - /// - /// Updates command value information of a selected asynchronous task - /// - /// Asynchronous Parameter Values - private void UOC_UpdateTaskCommand(AsyncProcessingServiceParameterValue asyncParameterValue) - { - AsyncProcessingServiceReturnValue asyncReturnValue = new AsyncProcessingServiceReturnValue(); - this.ReturnValue = asyncReturnValue; - - LayerD myDao = new LayerD(this.GetDam()); - myDao.UpdateTaskCommand(asyncParameterValue, asyncReturnValue); - } - - #endregion - - #region StopAllTask - - /// - /// Set stop command for all running asynchronous task - /// - /// Asynchronous Parameter Values - private void UOC_StopAllTask(AsyncProcessingServiceParameterValue asyncParameterValue) - { - AsyncProcessingServiceReturnValue asyncReturnValue = new AsyncProcessingServiceReturnValue(); - this.ReturnValue = asyncReturnValue; - - LayerD myDao = new LayerD(this.GetDam()); - myDao.StopAllTask(asyncParameterValue, asyncReturnValue); - } - - #endregion - - #endregion - - #region Select - - #region SelectCommand - - /// - /// Selects user command from Database through LayerD - /// - /// - private void UOC_SelectCommand(AsyncProcessingServiceParameterValue asyncParameterValue) - { - AsyncProcessingServiceReturnValue asyncReturnValue = new AsyncProcessingServiceReturnValue(); - this.ReturnValue = asyncReturnValue; - - LayerD myDao = new LayerD(this.GetDam()); - myDao.SelectCommand(asyncParameterValue, asyncReturnValue); - } - - #endregion - - #region SelectTask - - /// - /// Selects Asynchronous task from LayerD - /// - /// Async Parameter Value - private void UOC_SelectTask(AsyncProcessingServiceParameterValue asyncParameterValue) - { - AsyncProcessingServiceReturnValue asyncReturnValue = new AsyncProcessingServiceReturnValue(); - this.ReturnValue = asyncReturnValue; - - LayerD myDao = new LayerD(this.GetDam()); - myDao.SelectTask(asyncParameterValue, asyncReturnValue); - - DataTable dt = (DataTable)asyncReturnValue.Obj; - asyncReturnValue.Obj = null; - - if (dt != null) - { - if (dt.Rows.Count != 0) - { - asyncReturnValue.TaskId = Convert.ToInt32(dt.Rows[0]["Id"]); - asyncReturnValue.UserId = dt.Rows[0]["UserId"].ToString(); - asyncReturnValue.ProcessName = dt.Rows[0]["ProcessName"].ToString(); - asyncReturnValue.Data = dt.Rows[0]["Data"].ToString(); - asyncReturnValue.NumberOfRetries = Convert.ToInt32(dt.Rows[0]["NumberOfRetries"]); - asyncReturnValue.ReservedArea = dt.Rows[0]["ReservedArea"].ToString(); - asyncReturnValue.CommandId = Convert.ToInt32(dt.Rows[0]["CommandId"]); - } - } - } - - #endregion - - #endregion - - #region TestConnection - - /// - /// Tests the connection with the specified database - /// - /// Async Parameter Value - private void UOC_TestConnection(AsyncProcessingServiceParameterValue asyncParameterValue) - { - LayerD myDao = new LayerD(this.GetDam()); - } - - #endregion - } - - #endregion -} diff --git a/root/programs/Frameworks/Infrastructure/Business/AsyncProcessingService/LayerD.cs b/root/programs/Frameworks/Infrastructure/Business/AsyncProcessingService/LayerD.cs deleted file mode 100644 index 7be6027e..00000000 --- a/root/programs/Frameworks/Infrastructure/Business/AsyncProcessingService/LayerD.cs +++ /dev/null @@ -1,358 +0,0 @@ -//********************************************************************************** -//* Copyright (C) 2007,2016 Hitachi Solutions,Ltd. -//********************************************************************************** - -#region Apache License -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#endregion - -//********************************************************************************** -//* クラス名 :LayerD -//* クラス日本語名 :LayerD -//* -//* 日時 更新者 内容 -//* ---------- ---------------- ------------------------------------------------- -//* 11/28/2014 Supragyan Created LayerD class for AsyncProcessing Service -//* 11/28/2014 Supragyan Created Insert,Update,Select method for AsyncProcessing Service -//* 04/14/2015 Sandeep Did code modification of update and select asynchronous task -//* 04/14/2015 Sandeep Did code implementation of SetSqlByFile3 to access the SQL from embedded resource -//* 05/28/2015 Sandeep Did code implementation to update Exception information to the database -//* 06/09/2015 Sandeep Implemented code to update stop command to all the running asynchronous task -//* Modified code to reset Exception information, before starting asynchronous task -//* 06/26/2015 Sandeep Removed the where condition command <> 'Abort' from the SelectTask asynchronous task, -//* to resolve unstable "Register" state, when you invoke [Abort] to AsyncTask, at this "Register" state -//********************************************************************************** - -using System; -using System.Data; -using System.Text; - -using Touryo.Infrastructure.Business.Dao; -using Touryo.Infrastructure.Public.Db; -using Touryo.Infrastructure.Public.IO; -using Touryo.Infrastructure.Public.Util; - -namespace Touryo.Infrastructure.Business.AsyncProcessingService -{ - /// - /// LayerD class for AsyncProcessing Service - /// - public class LayerD : MyBaseDao - { - /// AsyncProcessingService用B層 - /// dam - public LayerD(BaseDam dam) : base(dam) { } - - #region SetSqlByFile3 - - /// - /// Get SQL query from the embedded resource assembly - /// - public void SetSqlByFile3(string filename) - { - // SQLファイルのEncoding情報の取得 - string sqlEncoding = GetConfigParameter.GetConfigValue(PubLiteral.SQL_ENCODING); - - if (string.IsNullOrEmpty(sqlEncoding)) - { - // デフォルト:UTF-8 - sqlEncoding = "utf-8"; - } - - string assemblyString = "Business"; - string assemblyNameSpace = "Touryo.Infrastructure.Business.AsyncProcessingService"; - string loadFileName = assemblyNameSpace + "." + filename; - - // Get SQL query from embedded resource file. - string commandText = EmbeddedResourceLoader.LoadAsString(assemblyString, loadFileName, Encoding.GetEncoding(sqlEncoding)); - - // Set sql command as text - this.SetSqlByCommand(commandText); - } - - #endregion - - #region Insert - - /// - /// Inserts async parameter values to database - /// - /// Asynchronous Parameter Values - /// Asynchronous Return Values - public void InsertTask(AsyncProcessingServiceParameterValue asyncParameterValue, AsyncProcessingServiceReturnValue asyncReturnValue) - { - string filename = "AsyncProcessingServiceInsert.sql"; - - // Get SQL query from file. - this.SetSqlByFile3(filename); - - // Set SQL parameter values - this.SetParameter("P2", asyncParameterValue.UserId); - this.SetParameter("P3", asyncParameterValue.ProcessName); - this.SetParameter("P4", asyncParameterValue.Data); - this.SetParameter("P5", asyncParameterValue.RegistrationDateTime); - this.SetParameter("P6", DBNull.Value); - this.SetParameter("P7", asyncParameterValue.NumberOfRetries); - this.SetParameter("P8", DBNull.Value); - this.SetParameter("P9", asyncParameterValue.StatusId); - this.SetParameter("P10", asyncParameterValue.ProgressRate); - this.SetParameter("P11", asyncParameterValue.CommandId); - this.SetParameter("P12", asyncParameterValue.ReservedArea); - - // Execute SQL query - asyncReturnValue.Obj = this.ExecInsUpDel_NonQuery(); - } - - #endregion - - #region Update - - #region UpdateTaskStart - - /// - /// Updates information in the database that the asynchronous task is started - /// - /// Asynchronous Parameter Values - /// Asynchronous Return Values - public void UpdateTaskStart(AsyncProcessingServiceParameterValue asyncParameterValue, AsyncProcessingServiceReturnValue asyncReturnValue) - { - string filename = "UpdateTaskStart.sql"; - - // Get SQL query from file. - this.SetSqlByFile3(filename); - - // Set SQL parameter values - this.SetParameter("P1", asyncParameterValue.TaskId); - this.SetParameter("P2", asyncParameterValue.ExecutionStartDateTime); - this.SetParameter("P3", asyncParameterValue.StatusId); - this.SetParameter("P4", DBNull.Value); - - // Execute SQL query - asyncReturnValue.Obj = this.ExecInsUpDel_NonQuery(); - } - - #endregion - - #region UpdateTaskRetry - - /// - /// Updates information in the database that the asynchronous task is failed and can be retried later - /// - /// Asynchronous Parameter Values - /// Asynchronous Return Values - public void UpdateTaskRetry(AsyncProcessingServiceParameterValue asyncParameterValue, AsyncProcessingServiceReturnValue asyncReturnValue) - { - string filename = "UpdateTaskRetry.sql"; - - // Get SQL query from file. - this.SetSqlByFile3(filename); - - // Set SQL parameter values - this.SetParameter("P1", asyncParameterValue.TaskId); - this.SetParameter("P2", asyncParameterValue.NumberOfRetries); - this.SetParameter("P3", asyncParameterValue.CompletionDateTime); - this.SetParameter("P4", asyncParameterValue.StatusId); - this.SetParameter("P5", asyncParameterValue.ExceptionInfo); - - // Execute SQL query - asyncReturnValue.Obj = this.ExecInsUpDel_NonQuery(); - } - - #endregion - - #region UpdateTaskFail - - /// - /// Updates information in the database that the asynchronous task is failed and abort this task [status=Abort] - /// - /// Asynchronous Parameter Values - /// Asynchronous Return Values - public void UpdateTaskFail(AsyncProcessingServiceParameterValue asyncParameterValue, AsyncProcessingServiceReturnValue asyncReturnValue) - { - string filename = "UpdateTaskFail.sql"; - - // Get SQL query from file. - this.SetSqlByFile3(filename); - - // Set SQL parameter values - this.SetParameter("P1", asyncParameterValue.TaskId); - this.SetParameter("P2", asyncParameterValue.CompletionDateTime); - this.SetParameter("P3", asyncParameterValue.StatusId); - this.SetParameter("P4", asyncParameterValue.ExceptionInfo); - - // Execute SQL query - asyncReturnValue.Obj = this.ExecInsUpDel_NonQuery(); - } - - #endregion - - #region UpdateTaskSuccess - - /// - /// Updates information in the database that the asynchronous task is completed - /// - /// Asynchronous Parameter Values - /// Asynchronous Return Values - public void UpdateTaskSuccess(AsyncProcessingServiceParameterValue asyncParameterValue, AsyncProcessingServiceReturnValue asyncReturnValue) - { - string filename = "UpdateTaskSuccess.sql"; - - // Get SQL query from file. - this.SetSqlByFile3(filename); - - // Set SQL parameter values - this.SetParameter("P1", asyncParameterValue.TaskId); - this.SetParameter("P2", asyncParameterValue.CompletionDateTime); - this.SetParameter("P3", asyncParameterValue.ProgressRate); - this.SetParameter("P4", asyncParameterValue.StatusId); - - // Execute SQL query - asyncReturnValue.Obj = this.ExecInsUpDel_NonQuery(); - } - - #endregion - - #region UpdateTaskProgress - - /// - /// Updates progress rate of the asynchronous task in the database. - /// - /// Asynchronous Parameter Values - /// Asynchronous Return Values - public void UpdateTaskProgress(AsyncProcessingServiceParameterValue asyncParameterValue, AsyncProcessingServiceReturnValue asyncReturnValue) - { - string filename = "UpdateTaskProgress.sql"; - - // Get SQL query from file. - this.SetSqlByFile3(filename); - - // Set SQL parameter values - this.SetParameter("P1", asyncParameterValue.TaskId); - this.SetParameter("P2", asyncParameterValue.ProgressRate); - - // Execute SQL query - asyncReturnValue.Obj = this.ExecInsUpDel_NonQuery(); - } - - #endregion - - #region UpdateTaskCommand - - /// - /// Updates command value information of a selected asynchronous task - /// - /// Asynchronous Parameter Values - /// Asynchronous Return Values - public void UpdateTaskCommand(AsyncProcessingServiceParameterValue asyncParameterValue, AsyncProcessingServiceReturnValue asyncReturnValue) - { - string filename = "UpdateTaskCommand.sql"; - - // Get SQL query from file. - this.SetSqlByFile3(filename); - - // Set SQL parameter values - this.SetParameter("P1", asyncParameterValue.TaskId); - this.SetParameter("P2", asyncParameterValue.CommandId); - - // Execute SQL query - asyncReturnValue.Obj = this.ExecInsUpDel_NonQuery(); - } - - #endregion - - #region StopAllTask - - /// - /// Set stop command for all running asynchronous task. - /// - /// Asynchronous Parameter Values - /// Asynchronous Return Values - public void StopAllTask(AsyncProcessingServiceParameterValue asyncParameterValue, AsyncProcessingServiceReturnValue asyncReturnValue) - { - string filename = "StopAllTask.sql"; - - // Get SQL query from file. - this.SetSqlByFile3(filename); - - // Set SQL parameter values - this.SetParameter("P1", asyncParameterValue.StatusId); - this.SetParameter("P2", asyncParameterValue.CommandId); - - // Execute SQL query - asyncReturnValue.Obj = this.ExecInsUpDel_NonQuery(); - } - - #endregion - - #endregion - - #region Select - - #region SelectCommand - - /// - /// Selects user command from database - /// - /// Asynchronous Parameter Values - /// Asynchronous Return Values - public void SelectCommand(AsyncProcessingServiceParameterValue asyncParameterValue, AsyncProcessingServiceReturnValue asyncReturnValue) - { - string filename = "SelectCommand.sql"; - - // Get SQL query from file. - this.SetSqlByFile3(filename); - - // Set SQL parameter values - this.SetParameter("P1", asyncParameterValue.TaskId); - - // Execute SQL query - asyncReturnValue.Obj = this.ExecSelectScalar(); - } - - #endregion - - #region SelectTask - - /// - /// To get Asynchronous Task from the database - /// - /// - /// - public void SelectTask(AsyncProcessingServiceParameterValue asyncParameterValue, AsyncProcessingServiceReturnValue asyncReturnValue) - { - string filename = "SelectTask.sql"; - - // Get SQL query from file. - this.SetSqlByFile3(filename); - - // Set SQL parameter values - this.SetParameter("P1", asyncParameterValue.RegistrationDateTime); - this.SetParameter("P2", asyncParameterValue.NumberOfRetries); - this.SetParameter("P3", (int)AsyncProcessingServiceParameterValue.AsyncStatus.Register); - this.SetParameter("P4", (int)AsyncProcessingServiceParameterValue.AsyncStatus.AbnormalEnd); - this.SetParameter("P7", asyncParameterValue.CompletionDateTime); - - DataTable dt = new DataTable(); - - // Get Asynchronous Task from the database - this.ExecSelectFill_DT(dt); - asyncReturnValue.Obj = dt; - } - - #endregion - - #endregion - } -} diff --git a/root/programs/Frameworks/Infrastructure/Business/Business.csproj b/root/programs/Frameworks/Infrastructure/Business/Business.csproj index 4a0ec293..7ccbc0d3 100644 --- a/root/programs/Frameworks/Infrastructure/Business/Business.csproj +++ b/root/programs/Frameworks/Infrastructure/Business/Business.csproj @@ -50,7 +50,7 @@ DEBUG;TRACE prompt 4 - bin\Debug\OpenTouryo.Business.xml + bin\Debug\OpenTouryo.Business.XML false @@ -75,12 +75,16 @@ ..\packages\Microsoft.Owin.3.1.0\lib\net45\Microsoft.Owin.dll True + + ..\packages\Microsoft.Owin.Security.3.1.0\lib\net45\Microsoft.Owin.Security.dll + True + ..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll True - - ..\packages\MySql.Data.6.9.9\lib\net45\MySql.Data.dll + + ..\packages\MySql.Data.6.9.12\lib\net45\MySql.Data.dll True @@ -91,24 +95,24 @@ ..\packages\Npgsql.3.2.5\lib\net451\Npgsql.dll True - - ..\packages\Touryo.Infrastructure.Public.Db.DamManagedOdp.2.2.0\lib\net46\OpenTouryo.DamManagedOdp.dll + + ..\packages\Touryo.Infrastructure.Public.Db.DamManagedOdp.2.3.0\lib\net46\OpenTouryo.DamManagedOdp.dll True - - ..\packages\Touryo.Infrastructure.Public.Db.DamMySQL.2.2.0\lib\net46\OpenTouryo.DamMySQL.dll + + ..\packages\Touryo.Infrastructure.Public.Db.DamMySQL.2.3.0\lib\net46\OpenTouryo.DamMySQL.dll True - - ..\packages\Touryo.Infrastructure.Public.Db.DamPstGrS.2.2.0\lib\net46\OpenTouryo.DamPstGrS.dll + + ..\packages\Touryo.Infrastructure.Public.Db.DamPstGrS.2.3.0\lib\net46\OpenTouryo.DamPstGrS.dll True - - ..\packages\Touryo.Infrastructure.Framework.2.2.0\lib\net46\OpenTouryo.Framework.dll + + ..\packages\Touryo.Infrastructure.Framework.2.3.0\lib\net46\OpenTouryo.Framework.dll True - - ..\packages\Touryo.Infrastructure.Public.2.2.0\lib\net46\OpenTouryo.Public.dll + + ..\packages\Touryo.Infrastructure.Public.2.3.0\lib\net46\OpenTouryo.Public.dll True @@ -164,11 +168,6 @@ - - - - - diff --git a/root/programs/Frameworks/Infrastructure/Business/Business/MyApsBaseLogic.cs b/root/programs/Frameworks/Infrastructure/Business/Business/MyApsBaseLogic.cs deleted file mode 100644 index 8b26956d..00000000 --- a/root/programs/Frameworks/Infrastructure/Business/Business/MyApsBaseLogic.cs +++ /dev/null @@ -1,678 +0,0 @@ -//********************************************************************************** -//* Copyright (C) 2007,2016 Hitachi Solutions,Ltd. -//********************************************************************************** - -#region Apache License -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#endregion - -//********************************************************************************** -//* クラス名 :MyApsBaseLogic -//* クラス日本語名 :自動振り分け機能付き業務コード親クラス2(サーバ用)(テンプレート) -//* -//* 作成者 :生技 西野 -//* 更新履歴 : -//* -//* 日時 更新者 内容 -//* ---------- ---------------- ------------------------------------------------- -//* 20xx/xx/xx XX XX 新規作成(テンプレート) -//* 2010/03/30 西野 大介 ログ フォーマットにメソッド名を追加 -//* 2010/09/24 西野 大介 共通引数クラス内にユーザ情報を格納したので -//* 2010/09/24 西野 大介 Damクラス内にユーザ情報を格納したので -//* 2011/01/24 西野 大介 上記コードが通るカバレージを修正 -//* 2011/01/31 西野 大介 Damがnullの場合は処理しないように修正 -//* 2012/02/09 西野 大介 OLEDB、ODBCのデータプロバイダ対応 -//* 2012/04/05 西野 大介 \n → \r\n 化 -//* 2012/06/18 西野 大介 OriginalStackTrace(ログ出力)の品質向上 -//* 2015/08/28 Sandeep Implemented code to create two dams -//* One dam for ABT asynchronous business task -//* Other dam for AMT asynchronous management task -//* 2017/02/28 西野 大介 ExceptionDispatchInfoを取り入れ、OriginalStackTraceを削除 -//* 2017/02/28 西野 大介 エラーログの見直し(その他の例外の場合、ex.ToString()を出力) -//********************************************************************************** - -using System; -using System.Runtime.ExceptionServices; - -using Touryo.Infrastructure.Business.Common; -using Touryo.Infrastructure.Framework.Business; -using Touryo.Infrastructure.Framework.Exceptions; -using Touryo.Infrastructure.Framework.Common; -using Touryo.Infrastructure.Public.Db; -using Touryo.Infrastructure.Public.Log; -using Touryo.Infrastructure.Public.Util; - -namespace Touryo.Infrastructure.Business.Business -{ - /// 自動振り分け機能付き業務コード親クラス2(サーバ用)(テンプレート) - /// (オーバーライドして)自由に利用できる。 - public abstract class MyApsBaseLogic : BaseLogic - { - /// 性能測定 - private PerformanceRecorder perfRec; - - /// Dam key value for asynchronous Business task - private string _damKeyforABT = "ABT"; - - /// Get dam key property to access asynchronous Business task - protected String DamKeyforABT - { - get - { - return this._damKeyforABT; - } - } - - /// Dam key value for asynchronous management task - private string _damKeyforAMT = "AMT"; - - /// Get dam key property to access asynchronous management task - protected String DamKeyforAMT - { - get - { - return this._damKeyforAMT; - } - } - - #region メソッド - - #region 処理の自動振り分け - - /// 自動振り分け処理 - /// 引数クラス - /// 戻り値クラス - protected override void UOC_DoAction(BaseParameterValue parameterValue, ref BaseReturnValue returnValue) - { - // メソッド名を生成 - string methodName = "UOC_" + parameterValue.MethodName; - - #region レイトバインドする - - object[] paramSet = new object[] { parameterValue }; - - try - { - // Latebind - Latebind.InvokeMethod(this, methodName, paramSet); - } - catch (System.Reflection.TargetInvocationException rtEx) - { - // スタックトレースを保って InnerException を throw - ExceptionDispatchInfo.Capture(rtEx.InnerException).Throw(); - } - finally - { - // レイトバインドにおいて、 - // ・ 戻り値(in)の場合、下位で生成した戻り値インスタンスは戻らない。 - // ・ 戻り値(ref, out)の場合、例外発生時は戻り値インスタンスは戻らない。 - // という問題がある。 - - // ∴ (特に後者の対応のため、) - // メンバ変数を使用して戻り値インスタンスを戻す。 - returnValue = this.ReturnValue; - } - - #endregion - } - - #endregion - - #region DB接続 - - /// データアクセス制御クラス(DAM)の生成し、コネクションを確立、トランザクションを開始する処理を実装 - /// 引数クラス - /// 分離レベル(DBMS毎の分離レベルの違いを理解して設定すること) - /// 業務コード親クラス1から利用される派生の末端 - protected override void UOC_ConnectionOpen( - BaseParameterValue parameterValue, - DbEnum.IsolationLevelEnum iso) - { - #region トランザクション属性取得例 - - //// クラスの属性、メソッドの属性から調査 - //MyAttribute[] aryMCA; - //MyAttribute[] aryMMA; - - //// クラスの属性を取得 - //MyAttribute.GetAttr(this, out aryMCA); - - //foreach (MyAttribute mca in aryMCA) - //{ - // Debug.WriteLine(this.GetType().ToString() + ".MyAttributeA = " + mca.MyAttributeA); - // Debug.WriteLine(this.GetType().ToString() + ".MyAttributeB = " + mca.MyAttributeB); - // Debug.WriteLine(this.GetType().ToString() + ".MyAttributeC = " + mca.MyAttributeC); - // Debug.WriteLine("+------------------+"); - //} - - //// メソッドの属性を取得 - //MethodInfo[] aryMtdInfo = this.GetType().GetMethods(); - - //foreach (MethodInfo mtdInfo in aryMtdInfo) - //{ - // MyAttribute.GetAttr(mtdInfo, out aryMMA); - - // foreach (MyAttribute mma in aryMMA) - // { - // Debug.WriteLine(mtdInfo.Name + ".MyAttributeA = " + mma.MyAttributeA); - // Debug.WriteLine(mtdInfo.Name + ".MyAttributeB = " + mma.MyAttributeB); - // Debug.WriteLine(mtdInfo.Name + ".MyAttributeC = " + mma.MyAttributeC); - // Debug.WriteLine("+------------------+"); - // } - //} - - #endregion - - // データアクセス制御クラス(DAM) - BaseDam damABT = null; - BaseDam damAMT = null; - - #region 接続 - - if (iso == DbEnum.IsolationLevelEnum.NotConnect) - { - // 接続しない - } - else - { - // 接続する - - string connstring = ""; - - #region データ プロバイダ選択 - - if (parameterValue.ActionType.Split('%')[0] == "SQL") - { - // SQL Server / SQL Client用のDamを生成 - damABT = new DamSqlSvr(); - damAMT = new DamSqlSvr(); - - // 接続文字列をロード - connstring = GetConfigParameter.GetConnectionString("ConnectionString_SQL"); - } - else if (parameterValue.ActionType.Split('%')[0] == "OLE") - { - // OLEDB.NET用のDamを生成 - damABT = new DamOLEDB(); - damAMT = new DamOLEDB(); - - // 接続文字列をロード - connstring = GetConfigParameter.GetConnectionString("ConnectionString_OLE"); - } - else if (parameterValue.ActionType.Split('%')[0] == "ODB") - { - // ODBC.NET用のDamを生成 - damABT = new DamODBC(); - damAMT = new DamODBC(); - - // 接続文字列をロード - connstring = GetConfigParameter.GetConnectionString("ConnectionString_ODBC"); - } - //else if (parameterValue.ActionType.Split('%')[0] == "ORA") - //{ - // // Oracle / Oracle Client用のDamを生成 - // damABT = new DamOraClient(); - // damAMT = new DamOraClient(); - - // // 接続文字列をロード - // connstring = GetConfigParameter.GetConnectionString("ConnectionString_ORA"); - //} - else if (parameterValue.ActionType.Split('%')[0] == "ODP") - { - // Oracle / ODP.NET用のDamを生成 - damABT = new DamManagedOdp(); - damAMT = new DamManagedOdp(); - - // 接続文字列をロード - connstring = GetConfigParameter.GetConnectionString("ConnectionString_ODP"); - } - //else if (parameterValue.ActionType.Split('%')[0] == "DB2") - //{ - // // DB2.NET用のDamを生成 - // damABT = new DamDB2(); - // damAMT = new DamDB2(); - - // // 接続文字列をロード - // connstring = GetConfigParameter.GetConnectionString("ConnectionString_DB2"); - //} - //else if (parameterValue.ActionType.Split('%')[0] == "HIR") - //{ - // // HiRDBデータプロバイダ用のDamを生成 - // dam = new DamHiRDB(); - - // // 接続文字列をロード - // connstring = GetConfigParameter.GetConnectionString("ConnectionString_HIR"); - //} - else if (parameterValue.ActionType.Split('%')[0] == "MCN") - { - // MySQL Cnn/NET用のDamを生成 - damABT = new DamMySQL(); - damAMT = new DamMySQL(); - - // 接続文字列をロード - connstring = GetConfigParameter.GetConnectionString("ConnectionString_MCN"); - } - else if (parameterValue.ActionType.Split('%')[0] == "NPS") - { - // PostgreSQL / Npgsql用のDamを生成 - damABT = new DamPstGrS(); - damAMT = new DamPstGrS(); - - // 接続文字列をロード - connstring = GetConfigParameter.GetConnectionString("ConnectionString_NPS"); - } - else - { - // ここは通らない - } - - #endregion - - if (damABT != null && damAMT != null) - { - // コネクションをオープンする。 - damABT.ConnectionOpen(connstring); - damAMT.ConnectionOpen(connstring); - - #region トランザクションを開始する。 - - if (iso == DbEnum.IsolationLevelEnum.User) - { - // 自動トランザクション(規定の分離レベル) - damABT.BeginTransaction(DbEnum.IsolationLevelEnum.NoTransaction); - } - else - { - // 自動トランザクション(指定の分離レベル) - damABT.BeginTransaction(iso); - } - damAMT.BeginTransaction(DbEnum.IsolationLevelEnum.NoTransaction); - - #endregion - - // ユーザ情報を格納する(ログ出力で利用)。 - damABT.Obj = ((MyParameterValue)parameterValue).User; - damAMT.Obj = ((MyParameterValue)parameterValue).User; - - // damを設定する。 - this.SetDam(this._damKeyforABT, damABT); - this.SetDam(this._damKeyforAMT, damAMT); - } - } - - #endregion - } - - #endregion - - #region 開始・終了処理 - - /// - /// B層の開始処理を実装 - /// - /// 引数クラス - /// 業務コード親クラス1から利用される派生の末端 - protected override void UOC_PreAction(BaseParameterValue parameterValue) - { - // ACCESSログ出力----------------------------------------------- - - MyParameterValue myPV = (MyParameterValue)parameterValue; - - // ------------ - // メッセージ部 - // ------------ - // ユーザ名, IPアドレス, レイヤ, - // 画面名, コントロール名, メソッド名, 処理名 - // ------------ - string strLogMessage = - "," + myPV.User.UserName + - "," + myPV.User.IPAddress + - "," + "----->>" + - "," + myPV.ScreenId + - "," + myPV.ControlId + - "," + myPV.MethodName + - "," + myPV.ActionType; - - // Log4Netへログ出力 - LogIF.InfoLog("ACCESS", strLogMessage); - - // ------------------------------------------------------------- - - // 性能測定開始 - this.perfRec = new PerformanceRecorder(); - this.perfRec.StartsPerformanceRecord(); - - } - - /// - /// B層の終了処理を実装 - /// - /// 引数クラス - /// 戻り値クラス - /// 業務コード親クラス1から利用される派生の末端 - protected override void UOC_AfterAction(BaseParameterValue parameterValue, BaseReturnValue returnValue) - { - // 性能測定終了 - this.perfRec.EndsPerformanceRecord(); - - // ACCESSログ出力----------------------------------------------- - - MyParameterValue myPV = (MyParameterValue)parameterValue; - - // ------------ - // メッセージ部 - // ------------ - // ユーザ名, IPアドレス, レイヤ, - // 画面名, コントロール名, メソッド名, 処理名 - // 処理時間(実行時間), 処理時間(CPU時間) - // ------------ - string strLogMessage = - "," + myPV.User.UserName + - "," + myPV.User.IPAddress + - "," + "<<-----" + - "," + myPV.ScreenId + - "," + myPV.ControlId + - "," + myPV.MethodName + - "," + myPV.ActionType + - "," + this.perfRec.ExecTime + - "," + this.perfRec.CpuTime; - - // Log4Netへログ出力 - LogIF.InfoLog("ACCESS", strLogMessage); - - // ------------------------------------------------------------- - } - - /// - /// B層のトランザクションのコミット後の終了処理を実装 - /// - /// 引数クラス - /// 戻り値クラス - /// 業務コード親クラス1から利用される派生の末端 - protected override void UOC_AfterTransaction(BaseParameterValue parameterValue, BaseReturnValue returnValue) - { - // TODO: - } - - #endregion - - #region 例外処理 - - /// - /// B層の業務例外による異常終了の後処理を実装するUOCメソッド。 - /// - /// 引数クラス - /// 戻り値クラス - /// BusinessApplicationException - /// 業務コード親クラス1から利用される派生の末端 - protected override void UOC_ABEND(BaseParameterValue parameterValue, BaseReturnValue returnValue, BusinessApplicationException baEx) - { - // 業務例外発生時の処理を実装 - // TODO: - - // nullチェック - if (this.perfRec == null) - { - // なにもしない - } - else - { - // 性能測定終了 - this.perfRec.EndsPerformanceRecord(); - - // ACCESSログ出力----------------------------------------------- - - MyParameterValue myPV = (MyParameterValue)parameterValue; - - // ------------ - // メッセージ部 - // ------------ - // ユーザ名, IPアドレス, レイヤ, - // 画面名, コントロール名, メソッド名, 処理名 - // 処理時間(実行時間), 処理時間(CPU時間) - // エラーメッセージID, エラーメッセージ等 - // ------------ - string strLogMessage = - "," + myPV.User.UserName + - "," + myPV.User.IPAddress + - "," + "<<-----" + - "," + myPV.ScreenId + - "," + myPV.ControlId + - "," + myPV.MethodName + - "," + myPV.ActionType + - "," + this.perfRec.ExecTime + - "," + this.perfRec.CpuTime + - "," + baEx.messageID + - "," + baEx.Message; // baEX - - // Log4Netへログ出力 - LogIF.WarnLog("ACCESS", strLogMessage); - } - - // ------------------------------------------------------------- - } - - /// - /// B層のシステム例外による異常終了の後処理を実装するUOCメソッド。 - /// - /// 引数クラス - /// 戻り値クラス - /// BusinessSystemException - /// 業務コード親クラス1から利用される派生の末端 - protected override void UOC_ABEND(BaseParameterValue parameterValue, BaseReturnValue returnValue, BusinessSystemException bsEx) - { - // システム例外発生時の処理を実装 - // TODO: - - // nullチェック - if (this.perfRec == null) - { - // なにもしない - } - else - { - // 性能測定終了 - this.perfRec.EndsPerformanceRecord(); - - // ACCESSログ出力----------------------------------------------- - - MyParameterValue myPV = (MyParameterValue)parameterValue; - - // ------------ - // メッセージ部 - // ------------ - // ユーザ名, IPアドレス, レイヤ, - // 画面名, コントロール名, メソッド名, 処理名 - // 処理時間(実行時間), 処理時間(CPU時間) - // エラーメッセージID, エラーメッセージ等 - // ------------ - string strLogMessage = - "," + myPV.User.UserName + - "," + myPV.User.IPAddress + - "," + "<<-----" + - "," + myPV.ScreenId + - "," + myPV.ControlId + - "," + myPV.MethodName + - "," + myPV.ActionType + - "," + this.perfRec.ExecTime + - "," + this.perfRec.CpuTime + - "," + bsEx.messageID + - "," + bsEx.Message + - "\r\n" + bsEx.StackTrace; // bsEX - - // Log4Netへログ出力 - LogIF.ErrorLog("ACCESS", strLogMessage); - } - - // ------------------------------------------------------------- - } - - /// - /// B層の一般的な例外による異常終了の後処理を実装するUOCメソッド。 - /// - /// 引数クラス - /// 戻り値クラス - /// Exception - /// 業務コード親クラス1から利用される派生の末端 - protected override void UOC_ABEND(BaseParameterValue parameterValue, ref BaseReturnValue returnValue, Exception ex) - { - // 一般的な例外発生時の処理を実装 - // TODO: - - // nullチェック - if (this.perfRec == null) - { - // なにもしない - - // スタックトレースを保って InnerException を throw - ExceptionDispatchInfo.Capture(ex).Throw(); - } - else - { - // 性能測定終了 - this.perfRec.EndsPerformanceRecord(); - - // キャスト - MyParameterValue myPV = (MyParameterValue)parameterValue; - - // システム例外に振り替える用のワーク - bool sysErrorFlag = false; - string sysErrorMessageID = ""; - string sysErrorMessage = ""; - - #region 例外の振替処理のIF文 - - if (ex.Message == "Other-Business") - { - // 業務例外へ変換 - returnValue.ErrorFlag = true; - returnValue.ErrorMessageID = "振替後"; - returnValue.ErrorMessage = "振替後"; - returnValue.ErrorInfo = "振り替える場合は、基本的にここを利用。"; - } - else if (ex.Message == "Other-System") - { - // システム例外へ振替 - sysErrorFlag = true; - sysErrorMessageID = "振替後"; - sysErrorMessage = "振替後"; - } - - #endregion - - #region ACCESSログ出力、リスローする・しない - - if (returnValue.ErrorFlag) - { - // 業務例外へ変換 - - // ------------ - // メッセージ部 - // ------------ - // ユーザ名, IPアドレス, レイヤ, - // 画面名, コントロール名, メソッド名, 処理名 - // 処理時間(実行時間), 処理時間(CPU時間) - // エラーメッセージID, エラーメッセージ等 - // ------------ - string strLogMessage = - "," + myPV.User.UserName + - "," + myPV.User.IPAddress + - "," + "<<-----" + - "," + myPV.ScreenId + - "," + myPV.ControlId + - "," + myPV.MethodName + - "," + myPV.ActionType + - "," + this.perfRec.ExecTime + - "," + this.perfRec.CpuTime + - "," + returnValue.ErrorMessageID + - "," + returnValue.ErrorMessage; // baEX - - // Log4Netへログ出力 - LogIF.WarnLog("ACCESS", strLogMessage); - } - else if (sysErrorFlag) - { - // システム例外へ振替 - - // ------------ - // メッセージ部 - // ------------ - // ユーザ名, IPアドレス, レイヤ, - // 画面名, コントロール名, メソッド名, 処理名 - // 処理時間(実行時間), 処理時間(CPU時間) - // エラーメッセージID, エラーメッセージ等 - // ------------ - string strLogMessage = - "," + myPV.User.UserName + - "," + myPV.User.IPAddress + - "," + "<<-----" + - "," + myPV.ScreenId + - "," + myPV.ControlId + - "," + myPV.MethodName + - "," + myPV.ActionType + - "," + this.perfRec.ExecTime + - "," + this.perfRec.CpuTime + - "," + sysErrorMessageID + - "," + sysErrorMessage + - "\r\n" + ex.StackTrace; // bsEX - - // Log4Netへログ出力 - LogIF.ErrorLog("ACCESS", strLogMessage); - - // 振替てスロー - throw new BusinessSystemException(sysErrorMessageID, sysErrorMessage); - } - else - { - // そのまま - - // ------------ - // メッセージ部 - // ------------ - // ユーザ名, IPアドレス, レイヤ, - // 画面名, コントロール名, メソッド名, 処理名 - // 処理時間(実行時間), 処理時間(CPU時間) - // エラーメッセージID, エラーメッセージ等 - // ------------ - string strLogMessage = - "," + myPV.User.UserName + - "," + myPV.User.IPAddress + - "," + "<<-----" + - "," + myPV.ScreenId + - "," + myPV.ControlId + - "," + myPV.MethodName + - "," + myPV.ActionType + - "," + this.perfRec.ExecTime + - "," + this.perfRec.CpuTime + - "," + "other Exception" + - "," + ex.Message + - "\r\n" + ex.ToString(); // ex - - // Log4Netへログ出力 - LogIF.ErrorLog("ACCESS", strLogMessage); - - // スタックトレースを保って InnerException を throw - ExceptionDispatchInfo.Capture(ex).Throw(); - } - - #endregion - } - } - - #endregion - - #endregion - } -} diff --git a/root/programs/Frameworks/Infrastructure/Business/Business/MyFcBaseLogic.cs b/root/programs/Frameworks/Infrastructure/Business/Business/MyFcBaseLogic.cs index ea15afe1..b9433089 100644 --- a/root/programs/Frameworks/Infrastructure/Business/Business/MyFcBaseLogic.cs +++ b/root/programs/Frameworks/Infrastructure/Business/Business/MyFcBaseLogic.cs @@ -38,6 +38,7 @@ //* 2012/06/18 西野 大介 OriginalStackTrace(ログ出力)の品質向上 //* 2017/02/28 西野 大介 ExceptionDispatchInfoを取り入れ、OriginalStackTraceを削除 //* 2017/02/28 西野 大介 エラーログの見直し(その他の例外の場合、ex.ToString()を出力) +//* 2018/03/29 西野 大介 .NET Standard対応で、削除機能に関連する処理を削除 //********************************************************************************** using System; @@ -173,6 +174,8 @@ protected override void UOC_ConnectionOpen( // 接続文字列をロード connstring = GetConfigParameter.GetConnectionString("ConnectionString_SQL"); } +#if NETCOREAPP2_0 +#else else if (parameterValue.ActionType.Split('%')[0] == "OLE") { // OLEDB.NET用のDamを生成 @@ -181,6 +184,7 @@ protected override void UOC_ConnectionOpen( // 接続文字列をロード connstring = GetConfigParameter.GetConnectionString("ConnectionString_OLE"); } +#endif else if (parameterValue.ActionType.Split('%')[0] == "ODB") { // ODBC.NET用のDamを生成 @@ -197,6 +201,8 @@ protected override void UOC_ConnectionOpen( // // 接続文字列をロード // connstring = GetConfigParameter.GetConnectionString("ConnectionString_ORA"); //} +#if NETCOREAPP2_0 +#else else if (parameterValue.ActionType.Split('%')[0] == "ODP") { // Oracle / ODP.NET用のDamを生成 @@ -205,6 +211,7 @@ protected override void UOC_ConnectionOpen( // 接続文字列をロード connstring = GetConfigParameter.GetConnectionString("ConnectionString_ODP"); } +#endif //else if (parameterValue.ActionType.Split('%')[0] == "DB2") //{ // // DB2.NET用のDamを生成 diff --git a/root/programs/Frameworks/Infrastructure/Business/Business_netcore20.csproj b/root/programs/Frameworks/Infrastructure/Business/Business_netcore20.csproj new file mode 100644 index 00000000..08061701 --- /dev/null +++ b/root/programs/Frameworks/Infrastructure/Business/Business_netcore20.csproj @@ -0,0 +1,57 @@ + + + + netcoreapp2.0 + Touryo.Infrastructure.Business + OpenTouryo.Business + true + + + + TRACE;DEBUG;NETCORE + ..\Build_netcore20\ + ..\Build_netcore20\netcoreapp2.0\OpenTouryo.Business.xml + portable + true + 1701;1702;NU1701 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/root/programs/Frameworks/Infrastructure/Business/Dao/CmnDao.cs b/root/programs/Frameworks/Infrastructure/Business/Dao/CmnDao.cs index fc609c6e..bc153a86 100644 --- a/root/programs/Frameworks/Infrastructure/Business/Dao/CmnDao.cs +++ b/root/programs/Frameworks/Infrastructure/Business/Dao/CmnDao.cs @@ -39,6 +39,7 @@ //* 2013/07/07 西野 大介 ExecGenerateSQL(SQL生成)メソッド(実行しない)を追加 //* 2014/11/20 Sandeep Implemented CommandTimeout property and SetCommandTimeout method. //* 2014/11/20 Sai removed IDbCommand property in SetCommandTimeout method. +//* 2018/08/07 西野 大介 ストアド実行のためCommandType.StoredProcedureを設定可能に。 //********************************************************************************** using System; @@ -57,6 +58,9 @@ public class CmnDao : MyBaseDao { #region インスタンス変数 + /// CommandType + private CommandType? _cmdType = null; + #region パラメタ /// ユーザ パラメタ(文字列置換)用ディクショナリ @@ -65,14 +69,16 @@ public class CmnDao : MyBaseDao /// パラメタ ライズド クエリのパラメタ用ディクショナリ private Dictionary DicParameter = new Dictionary(); + #region 追加のDictionary /// パラメタ ライズド クエリの指定されたパラメータ(の型)を保持するディクショナリ private Dictionary DicParameterType = new Dictionary(); /// パラメタ ライズド クエリの指定されたパラメータ(のサイズ)を保持するディクショナリ private Dictionary DicParameterSize = new Dictionary(); /// パラメタ ライズド クエリの指定されたパラメータ(の方向)を保持するディクショナリ private Dictionary DicParameterDirection = new Dictionary(); + #endregion - #endregion + #endregion #region パラメタの制御 @@ -252,6 +258,13 @@ public int CommandTimeout /// 自由に利用できる。 public CmnDao(BaseDam dam) : base(dam) { } + /// コンストラクタ + /// 自由に利用できる。 + public CmnDao(BaseDam dam, CommandType cmdType) : base(dam) + { + this._cmdType = cmdType; + } + #endregion #region クエリ メソッド @@ -384,12 +397,27 @@ private void SetSQL() if (this._sQLFileName != "") { // ファイルから - this.SetSqlByFile2(this._sQLFileName); + if (this._cmdType.HasValue) + { + this.SetSqlByFile2(this._sQLFileName, this._cmdType.Value); + } + else + { + this.SetSqlByFile2(this._sQLFileName); + } } else if (this._sQLText != "") { // テキストから - this.SetSqlByCommand(this._sQLText); + if (this._cmdType.HasValue) + { + this.SetSqlByCommand(this._sQLText, this._cmdType.Value); + } + else + { + this.SetSqlByCommand(this._sQLText); + } + } else { diff --git a/root/programs/Frameworks/Infrastructure/Business/Dao/MyBaseDao.cs b/root/programs/Frameworks/Infrastructure/Business/Dao/MyBaseDao.cs index cca89074..bb98b9f3 100644 --- a/root/programs/Frameworks/Infrastructure/Business/Dao/MyBaseDao.cs +++ b/root/programs/Frameworks/Infrastructure/Business/Dao/MyBaseDao.cs @@ -33,10 +33,12 @@ //* 2012/06/14 西野 大介 SetSqlByFile2を追加(SetSqlByFile強化版) //* ・sqlTextFilePathを自動連結 //* ・EmbeddedResourceLoaderに対応 +//* 2018/08/07 西野 大介 CommandType.StoredProcedureを設定可能に。 //********************************************************************************** using System; using System.IO; +using System.Data; using Touryo.Infrastructure.Business.Util; using Touryo.Infrastructure.Framework.Dao; @@ -56,20 +58,45 @@ public abstract class MyBaseDao : BaseDao /// SetSqlByFileの強化版メソッド /// ファイル名 public void SetSqlByFile2(string sQLFileName) + { + this.SetSqlByFile2(sQLFileName, null); + } + + /// SetSqlByFileの強化版メソッド + /// ファイル名 + /// CommandType + public void SetSqlByFile2(string sQLFileName, CommandType? cmdType) { // SQLを設定する。 if (MyBaseDao.UseEmbeddedResource) { // 埋め込まれたリソースファイル - this.SetSqlByFile( + if (cmdType.HasValue) + { + this.SetSqlByFile( + GetConfigParameter.GetConfigValue("sqlTextFilePath") + "." + sQLFileName, cmdType.Value); + } + else + { + this.SetSqlByFile( GetConfigParameter.GetConfigValue("sqlTextFilePath") + "." + sQLFileName); + } } else { // 通常のファイル - this.SetSqlByFile( - Path.Combine( - GetConfigParameter.GetConfigValue("sqlTextFilePath"), sQLFileName)); + if (cmdType.HasValue) + { + this.SetSqlByFile( + Path.Combine( + GetConfigParameter.GetConfigValue("sqlTextFilePath"), sQLFileName), cmdType.Value); + } + else + { + this.SetSqlByFile( + Path.Combine( + GetConfigParameter.GetConfigValue("sqlTextFilePath"), sQLFileName)); + } } } diff --git a/root/programs/Frameworks/Infrastructure/Business/Presentation/MyBaseAsyncApiController.cs b/root/programs/Frameworks/Infrastructure/Business/Presentation/MyBaseAsyncApiController.cs index 626d8bd3..e9f2e116 100644 --- a/root/programs/Frameworks/Infrastructure/Business/Presentation/MyBaseAsyncApiController.cs +++ b/root/programs/Frameworks/Infrastructure/Business/Presentation/MyBaseAsyncApiController.cs @@ -19,8 +19,8 @@ #endregion //********************************************************************************** -//* クラス名 :MyBaseApiControllerAsync (ActionFilterAttribute) -//* クラス日本語名 :非同期 ASP.NET WebAPI用 ベーククラス2(テンプレート) +//* クラス名 :MyBaseAsyncApiController (Filters) +//* クラス日本語名 :非同期 ASP.NET WebAPI用 ベーククラス2相当(テンプレート) //* //* 作成者 :生技 西野 //* 更新履歴 : @@ -73,6 +73,8 @@ public class MyBaseAsyncApiController : ActionFilterAttribute, IAuthenticationFi /// ActionName protected string ActionName = ""; + #region 認証・認可 + /// /// プロセスが承認を要求したときに呼び出します。 /// https://msdn.microsoft.com/ja-jp/library/dn314618.aspx @@ -98,6 +100,8 @@ public async Task ChallengeAsync(HttpAuthenticationChallengeContext authenticati authenticationChallengeContext.Result = new ResultWithChallenge(authenticationChallengeContext.Result); return; } + + #endregion #region OnAction @@ -231,7 +235,7 @@ private async Task OutputErrorLog(HttpActionExecutedContext exceptionContext) string strLogMessage = "," + userName + // (this.UserInfo != null ? this.UserInfo.UserName : "null") + "," + ipAddress + //(this.UserInfo != null ? this.UserInfo.IPAddress : "null") + - "," + "----->>" + + "," + "<-----" + "," + this.ControllerName + "," + this.ActionName + "(ExecuteExceptionFilterAsync)" + "," + //this.perfRec.ExecTime + @@ -283,21 +287,23 @@ private async Task GetUserInfoAsync(HttpAuthenticationContext authenticationCont // ------------------------------------------------------------- List claims = null; - if (authenticationContext.Request.Headers.Authorization.Scheme.ToLower() == "bearer") + if (authenticationContext.Request.Headers.Authorization != null) { - string access_token = authenticationContext.Request.Headers.Authorization.Parameter; + if (authenticationContext.Request.Headers.Authorization.Scheme.ToLower() == "bearer") + { + string access_token = authenticationContext.Request.Headers.Authorization.Parameter; - string sub = ""; - List roles = null; - List scopes = null; - JObject jobj = null; + string sub = ""; + List roles = null; + List scopes = null; + JObject jobj = null; - if (JwtToken.Verify(access_token, out sub, out roles, out scopes, out jobj)) - { + if (JwtToken.Verify(access_token, out sub, out roles, out scopes, out jobj)) + { - // ActionFilterAttributeとApiController間の情報共有はcontext.Principalを使用する。 - // ★ 必要であれば、他の業務共通引継ぎ情報などをロードする。 - claims = new List() + // ActionFilterAttributeとApiController間の情報共有はcontext.Principalを使用する。 + // ★ 必要であれば、他の業務共通引継ぎ情報などをロードする。 + claims = new List() { new Claim(ClaimTypes.Name, sub), new Claim(ClaimTypes.Role, string.Join(",", roles)), @@ -305,24 +311,32 @@ private async Task GetUserInfoAsync(HttpAuthenticationContext authenticationCont new Claim("IpAddress", MyBaseAsyncApiController.GetClientIpAddress(authenticationContext.Request)) }; - // The request message contains valid credential - authenticationContext.Principal = new ClaimsPrincipal(new List { new ClaimsIdentity(claims, "Token") }); - return; + // The request message contains valid credential. + authenticationContext.Principal = new ClaimsPrincipal(new List { new ClaimsIdentity(claims, "Token") }); + + return; + } + else + { + // JWTの内容検証に失敗 + } } else { - // JWTの内容検証に失敗 + // Authorization HeaderがBearerでない。 } } else { - // Authorization: Bearer Headerが存在しない。 + // Authorization Headerが存在しない。 } - // 未認証状態 - // The request message contains invalid credential + #region 未認証状態の場合の扱い + + // The request message contains invalid credential. //context.ErrorResult = new UnauthorizedResult(new AuthenticationHeaderValue[0], context.Request); + // 未認証状態のclaimsを作成格納 claims = new List() { new Claim(ClaimTypes.Name, "未認証"), @@ -332,7 +346,10 @@ private async Task GetUserInfoAsync(HttpAuthenticationContext authenticationCont }; authenticationContext.Principal = new ClaimsPrincipal(new List { new ClaimsIdentity(claims, "Token") }); + return; + + #endregion } /// GetClientIpAddress diff --git a/root/programs/Frameworks/Infrastructure/Business/Presentation/MyBaseAsyncApiControllerCore.cs b/root/programs/Frameworks/Infrastructure/Business/Presentation/MyBaseAsyncApiControllerCore.cs new file mode 100644 index 00000000..d62c9671 --- /dev/null +++ b/root/programs/Frameworks/Infrastructure/Business/Presentation/MyBaseAsyncApiControllerCore.cs @@ -0,0 +1,350 @@ +//********************************************************************************** +//* Copyright (C) 2007,2016 Hitachi Solutions,Ltd. +//********************************************************************************** + +#region Apache License +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#endregion + +//********************************************************************************** +//* クラス名 :MyBaseAsyncApiControllerCore (Filters) +//* クラス日本語名 :非同期 ASP.NET Core WebAPI用 ベーククラス2相当(テンプレート) +//* +//* 作成者 :生技 西野 +//* 更新履歴 : +//* +//* 日時 更新者 内容 +//* ---------- ---------------- ------------------------------------------------- +//* 2018/04/09 西野 大介 新規作成 +//********************************************************************************** + +using System; +using System.Linq; +using System.Collections.Generic; +using System.Threading.Tasks; +using System.Security.Claims; + +using Microsoft.AspNetCore.Mvc.Filters; +using Microsoft.Extensions.Primitives; + +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +using Touryo.Infrastructure.Framework.StdMigration; +using Touryo.Infrastructure.Framework.Authentication; +using Touryo.Infrastructure.Framework.Exceptions; +using Touryo.Infrastructure.Framework.Util; +using Touryo.Infrastructure.Public.Log; +using Touryo.Infrastructure.Public.Util; + +namespace Touryo.Infrastructure.Business.Presentation +{ + /// 非同期 ASP.NET WebAPI用 ベーククラス2 + /// (ActionFilterAttributeとして)自由に利用できる。 + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)] + public class MyBaseAsyncApiController : ActionFilterAttribute, IAsyncAuthorizationFilter, IAsyncActionFilter, IExceptionFilter + { + /// 性能測定 + private PerformanceRecorder perfRec; + + ///// UserInfo + //protected MyUserInfo UserInfo; + + /// ControllerName + protected string ControllerName = ""; + + /// ActionName + protected string ActionName = ""; + + #region 認証・認可 + + /// AuthorizationFilterContext + /// AuthorizationFilterContext + public async Task OnAuthorizationAsync(AuthorizationFilterContext authenticationContext) + { + // 認証ユーザ情報をメンバにロードする + await this.GetUserInfoAsync(authenticationContext); + } + + #endregion + + #region OnAction + + /// + /// アクション メソッドの呼び出し前に発生します(netcore)。 + /// https://docs.microsoft.com/ja-jp/dotnet/api/microsoft.aspnetcore.mvc.filters.actionfilterattribute.onactionexecutionasync + /// + /// HttpActionContext + /// ActionExecutionDelegate + public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) + { + #region OnActionExecutingAsyncから移行 + + // Claimを取得する。 + string userName, roles, scopes, ipAddress; + MyBaseAsyncApiController.GetClaims(out userName, out roles, out scopes, out ipAddress); + + // 権限チェック ------------------------------------------------ + // ・・・ + // ------------------------------------------------------------- + + // 閉塞チェック ------------------------------------------------ + // ・・・ + // ------------------------------------------------------------- + + // 性能測定開始 + this.perfRec = new PerformanceRecorder(); + this.perfRec.StartsPerformanceRecord(); + + // ------------ + // メッセージ部 + // ------------ + // ユーザ名, IPアドレス, + // レイヤ, 画面名, コントロール名, 処理名 + // 処理時間(実行時間), 処理時間(CPU時間) + // エラーメッセージID, エラーメッセージ等 + // ------------ + + string strLogMessage = + "," + userName + //this.UserInfo.UserName + + "," + ipAddress + //this.UserInfo.IPAddress + + "," + "----->" + + "," + this.ControllerName + + "," + this.ActionName + "(OnActionExecuting)"; + + LogIF.InfoLog("ACCESS", strLogMessage); + + // 性能測定終了 + this.perfRec.EndsPerformanceRecord(); + + #endregion + + await base.OnActionExecutionAsync(context, next); + + #region OnActionExecutedAsyncから移行 + + // ------------ + // メッセージ部 + // ------------ + // ユーザ名, IPアドレス, + // レイヤ, 画面名, コントロール名, 処理名 + // 処理時間(実行時間), 処理時間(CPU時間) + // エラーメッセージID, エラーメッセージ等 + // ----------- + + strLogMessage = + "," + userName + //this.UserInfo.UserName + + "," + ipAddress + //this.UserInfo.IPAddress + + "," + "<-----" + + "," + this.ControllerName + + "," + this.ActionName + "(OnActionExecuted)" + + "," + perfRec.ExecTime + + "," + perfRec.CpuTime; + + LogIF.InfoLog("ACCESS", strLogMessage); + + #endregion + } + + #endregion + + #region OnException + + /// + /// 非同期の例外フィルターを実行します。 + /// https://msdn.microsoft.com/ja-jp/library/hh835353.aspx + /// + /// HttpActionExecutedContext + public void OnException(ExceptionContext exceptionContext) + { + // エラーログの出力 + this.OutputErrorLog(exceptionContext); + } + + /// エラーログの出力 + /// HttpActionExecutedContext + private void OutputErrorLog(ExceptionContext exceptionContext) + { + // 非同期ControllerのInnerException対策(底のExceptionを取得する)。 + Exception ex = exceptionContext.Exception; + Exception bottomException = ex; + while (bottomException.InnerException != null) + { + bottomException = bottomException.InnerException; + } + + // ------------ + // メッセージ部 + // ------------ + // ユーザ名, IPアドレス, + // レイヤ, 画面名, コントロール名, 処理名 + // 処理時間(実行時間), 処理時間(CPU時間) + // エラーメッセージID, エラーメッセージ等 + // ------------ + + // Claimを取得する。 + string userName, roles, scopes, ipAddress; + MyBaseAsyncApiController.GetClaims(out userName, out roles, out scopes, out ipAddress); + + string strLogMessage = + "," + userName + // (this.UserInfo != null ? this.UserInfo.UserName : "null") + + "," + ipAddress + //(this.UserInfo != null ? this.UserInfo.IPAddress : "null") + + "," + "<-----" + + "," + this.ControllerName + + "," + this.ActionName + "(ExecuteExceptionFilterAsync)" + + "," + //this.perfRec.ExecTime + + "," + //this.perfRec.CpuTime + + "," + GetExceptionMessageID(bottomException) + + "," + bottomException.Message + "\r\n" + + "," + bottomException.StackTrace + "\r\n" + + "," + ex.ToString(); // Exception.ToString()はRootのExceptionに対して行なう。 + + LogIF.ErrorLog("ACCESS", strLogMessage); + } + + /// ExceptionのMessageIDを返す。 + /// Exception + /// ExceptionのMessageID + private string GetExceptionMessageID(Exception ex) + { + // Check exception type + if (ex is BusinessSystemException) + { + // システム例外 + BusinessSystemException bsEx = (BusinessSystemException)ex; + return bsEx.messageID; + } + else if (ex is FrameworkException) + { + // フレームワーク例外 + FrameworkException fxEx = (FrameworkException)ex; + return fxEx.messageID; + } + else + { + // それ以外の例外 + return "other Exception"; + } + } + + #endregion + + #region 情報取得用 + + /// ユーザ情報を取得する + /// AuthorizationFilterContext + private async Task GetUserInfoAsync(AuthorizationFilterContext authorizationContext) + { + // カスタム認証処理 -------------------------------------------- + // Authorization: Bearer ヘッダから + // JWTアサーションを処理し、認証、UserInfoを生成するなど。 + // ------------------------------------------------------------- + List claims = null; + + if (authorizationContext.HttpContext.Request.Headers != null) + { + StringValues authHeaders = ""; + + if (authorizationContext.HttpContext.Request.Headers.TryGetValue("Authorization", out authHeaders)) + { + string access_token = authHeaders[0].Split(' ')[1]; + + string sub = ""; + List roles = null; + List scopes = null; + JObject jobj = null; + + if (JwtToken.Verify(access_token, out sub, out roles, out scopes, out jobj)) + { + + // ActionFilterAttributeとApiController間の情報共有はcontext.Principalを使用する。 + // ★ 必要であれば、他の業務共通引継ぎ情報などをロードする。 + claims = new List() + { + new Claim(ClaimTypes.Name, sub), + new Claim(ClaimTypes.Role, string.Join(",", roles)), + new Claim("Scopes", string.Join(",", scopes)), + new Claim("IpAddress", MyBaseAsyncApiController.GetClientIpAddress()) + }; + + // ClaimsPrincipalを設定 + MyHttpContext.Current.User = new ClaimsPrincipal(new ClaimsIdentity(claims, "Token")); + + return; + } + else + { + // JWTの内容検証に失敗 + } + } + else + { + // Authorization HeaderがBearerでない。 + } + } + else + { + // Authorization Headerが存在しない。 + } + + #region 未認証状態の場合の扱い + + // The request message contains invalid credential + //context.ErrorResult = new UnauthorizedResult(new AuthenticationHeaderValue[0], context.Request); + + // 未認証状態のclaimsを作成格納 + claims = new List() + { + new Claim(ClaimTypes.Name, "未認証"), + new Claim(ClaimTypes.Role, ""), + new Claim("Scopes", ""), + new Claim("IpAddress", MyBaseAsyncApiController.GetClientIpAddress()) + }; + + // The request message contains valid credential. + MyHttpContext.Current.User.AddIdentity(new ClaimsIdentity(claims, "Token")); + + return; + + #endregion + } + + /// GetClientIpAddress + /// IPAddress(文字列) + private static string GetClientIpAddress() + { + return (new GetClientIpAddress()).GetAddress(); + } + + /// GetClaims + /// string + /// string + /// string + /// string + public static void GetClaims(out string userName, out string roles, out string scopes, out string ipAddress) + { + // MyHttpContext.Current.User.Identity側ではなく、Identities側に入っている。 + // Identityは認証ミドルウェアを使用する必要がある?(coreでjwtをどう処理するのか?) + IEnumerable claims = + MyHttpContext.Current.User.Identities.FirstOrDefault(c => c.AuthenticationType == "Token").Claims; + userName = claims.FirstOrDefault(c => c.Type == ClaimTypes.Name).Value; + roles = claims.FirstOrDefault(c => c.Type == ClaimTypes.Role).Value; + scopes = claims.FirstOrDefault(c => c.Type == "Scopes").Value; + ipAddress = claims.FirstOrDefault(c => c.Type == "IpAddress").Value; + } + + #endregion + } +} diff --git a/root/programs/Frameworks/Infrastructure/Business/Presentation/MyBaseController.cs b/root/programs/Frameworks/Infrastructure/Business/Presentation/MyBaseController.cs index 73990af1..820d8591 100644 --- a/root/programs/Frameworks/Infrastructure/Business/Presentation/MyBaseController.cs +++ b/root/programs/Frameworks/Infrastructure/Business/Presentation/MyBaseController.cs @@ -56,6 +56,7 @@ //* 2017/02/28 西野 大介 ExceptionDispatchInfoを取り入れ、OriginalStackTraceを削除 //* 2017/02/28 西野 大介 TransferErrorScreen2のErrorMessage生成処理の見直し。 //* 2017/02/28 西野 大介 エラーログの見直し(その他の例外の場合、ex.ToString()を出力) +//* 2018/07/19 西野 大介 復元後のユーザー情報をSessionに設定するコードを追加 //********************************************************************************** using System; @@ -293,33 +294,32 @@ public static MyUserInfo GetUserInfo2() { // 取得を試みる。 userInfo = (MyUserInfo)UserInfoHandle.GetUserInformation(); - } - - // nullチェック - if (userInfo == null) - { - // nullの場合、仮の値を生成 / 設定する。 - string userName = System.Threading.Thread.CurrentPrincipal.Identity.Name; - if (userName == null || userName == "") - { - // 未認証状態 - userInfo = new MyUserInfo("未認証", HttpContext.Current.Request.UserHostAddress); - } - else + // nullチェック + if (userInfo == null) { - // 認証状態 - userInfo = new MyUserInfo(userName, HttpContext.Current.Request.UserHostAddress); - // 必要に応じて認証チケットの - // ユーザ名からユーザ情報を復元する。 + // nullの場合、仮の値を生成 / 設定する。 + string userName = System.Threading.Thread.CurrentPrincipal.Identity.Name; + + if (userName == null || userName == "") + { + // 未認証状態 + userInfo = new MyUserInfo("未認証", HttpContext.Current.Request.UserHostAddress); + } + else + { + // 認証状態 + userInfo = new MyUserInfo(userName, HttpContext.Current.Request.UserHostAddress); + + // 必要に応じて認証チケットのユーザ名からユーザ情報を復元する。 + // ★ 必要であれば、他の業務共通引継ぎ情報などをロードする。 + // ・・・ + + // 復元したユーザ情報をセット + UserInfoHandle.SetUserInformation(userInfo); + } } } - else - { - // nullで無い場合、取得した値を設定する。 - } - - // ★ 必要であれば、他の業務共通引継ぎ情報などをロードする。 // 値を戻す。 return userInfo; @@ -903,7 +903,7 @@ public static void TransferErrorScreen2(Exception ex) #endregion - #region マスタ ページ上のフレームワーク対象コントロール + #region マスタ ページ上のフレームワーク対象コントロール(不要な場合は削除してく下さい) #region sampleScreen.masterマスタ ページ上のフレームワーク対象コントロールの、共通イベントのUOCメソッド diff --git a/root/programs/Frameworks/Infrastructure/Business/Presentation/MyBaseMVController.cs b/root/programs/Frameworks/Infrastructure/Business/Presentation/MyBaseMVController.cs index e09f22e8..0c8799a1 100644 --- a/root/programs/Frameworks/Infrastructure/Business/Presentation/MyBaseMVController.cs +++ b/root/programs/Frameworks/Infrastructure/Business/Presentation/MyBaseMVController.cs @@ -44,6 +44,7 @@ //* 2017/02/28 西野 大介 OnExceptionのErrorMessage生成処理の見直し。 //* 2017/02/28 西野 大介 TransferErrorScreenメソッドを追加した。 //* 2017/02/28 西野 大介 エラーログの見直し(その他の例外の場合、ex.ToString()を出力) +//* 2018/07/19 西野 大介 復元後のユーザー情報をSessionに設定するコードを追加 //********************************************************************************** using System; @@ -361,29 +362,29 @@ protected override void OnResultExecuted(ResultExecutedContext filterContext) #region OnException /// アクションでハンドルされない例外が発生したときに呼び出されます。 - /// + /// /// 型: System.Web.Mvc.ResultExecutingContext /// 現在の要求およびアクション結果に関する情報。 /// /// /// web.config に customErrors mode="on" を追記(無い場合は、OnExceptionメソッドが動かない /// - protected override void OnException(ExceptionContext filterContext) + protected override void OnException(ExceptionContext exceptionContext) { // Calling base class method. - base.OnException(filterContext); + base.OnException(exceptionContext); // エラーログの出力 - this.OutputErrorLog(filterContext); + this.OutputErrorLog(exceptionContext); // エラー画面に画面遷移する - this.TransferErrorScreen(filterContext); + this.TransferErrorScreen(exceptionContext); } /// エラーログの出力 - /// ExceptionContext - private void OutputErrorLog(ExceptionContext filterContext) + /// ExceptionContext + private void OutputErrorLog(ExceptionContext exceptionContext) { // 非同期ControllerのInnerException対策(底のExceptionを取得する)。 - Exception ex = filterContext.Exception; + Exception ex = exceptionContext.Exception; Exception bottomException = ex; while (bottomException.InnerException != null) { @@ -402,7 +403,7 @@ private void OutputErrorLog(ExceptionContext filterContext) string strLogMessage = "," + (this.UserInfo != null ? this.UserInfo.UserName : "null") + "," + (this.UserInfo != null ? this.UserInfo.IPAddress : "null") + - "," + "----->>" + + "," + "<-----" + "," + this.ControllerName + "," + this.ActionName + "(OnException)" + "," + //this.perfRec.ExecTime + @@ -416,11 +417,11 @@ private void OutputErrorLog(ExceptionContext filterContext) } /// 例外発生時に、エラー画面に画面遷移 - /// ExceptionContext - private void TransferErrorScreen(ExceptionContext filterContext) + /// ExceptionContext + private void TransferErrorScreen(ExceptionContext exceptionContext) { // 非同期ControllerのInnerException対策(底のExceptionを取得する)。 - Exception ex = filterContext.Exception; + Exception ex = exceptionContext.Exception; Exception bottomException = ex; while (bottomException.InnerException != null) { @@ -477,25 +478,25 @@ private void TransferErrorScreen(ExceptionContext filterContext) // Add Form information to Session Session[FxHttpContextIndex.FORMS_INFORMATION] = Request.Form; - + #endregion #region エラー画面へ画面遷移 - filterContext.ExceptionHandled = true; - filterContext.HttpContext.Response.Clear(); + exceptionContext.ExceptionHandled = true; + exceptionContext.HttpContext.Response.Clear(); - if (filterContext.HttpContext.Request.IsAjaxRequest()) + if (exceptionContext.HttpContext.Request.IsAjaxRequest()) { - filterContext.Result = new JavaScriptResult() { Script = "location.href = '" + errorScreenPath + "'" }; + exceptionContext.Result = new JavaScriptResult() { Script = "location.href = '" + errorScreenPath + "'" }; } - else if (filterContext.IsChildAction) + else if (exceptionContext.IsChildAction) { - filterContext.Result = new ContentResult() { Content = "" }; + exceptionContext.Result = new ContentResult() { Content = "" }; } else { - filterContext.Result = new RedirectResult(errorScreenPath); + exceptionContext.Result = new RedirectResult(errorScreenPath); } #endregion @@ -542,33 +543,32 @@ private void GetUserInfo() { // 取得を試みる。 this.UserInfo = (MyUserInfo)UserInfoHandle.GetUserInformation(); - } - - // nullチェック - if (this.UserInfo == null) - { - // nullの場合、仮の値を生成 / 設定する。 - string userName = System.Threading.Thread.CurrentPrincipal.Identity.Name; - if (userName == null || userName == "") + // nullチェック + if (this.UserInfo == null) { - // 未認証状態 - this.UserInfo = new MyUserInfo("未認証", this.HttpContext.Request.UserHostAddress); + // nullの場合、仮の値を生成 / 設定する。 + string userName = System.Threading.Thread.CurrentPrincipal.Identity.Name; + + if (userName == null || userName == "") + { + // 未認証状態 + this.UserInfo = new MyUserInfo("未認証", this.HttpContext.Request.UserHostAddress); + } + else + { + // 認証状態 + this.UserInfo = new MyUserInfo(userName, this.HttpContext.Request.UserHostAddress); + + // 必要に応じて認証チケットのユーザ名からユーザ情報を復元する。 + // ★ 必要であれば、他の業務共通引継ぎ情報などをロードする。 + // ・・・ + + // 復元したユーザ情報をセット + UserInfoHandle.SetUserInformation(this.UserInfo); + } } - else - { - // 認証状態 - this.UserInfo = new MyUserInfo(userName, this.HttpContext.Request.UserHostAddress); - // 必要に応じて認証チケットの - // ユーザ名からユーザ情報を復元する。 - } - } - else - { - // nullで無い場合、取得した値を設定する。 - } - - // ★ 必要であれば、他の業務共通引継ぎ情報などをロードする。 + } } /// ルーティング情報を取得する diff --git a/root/programs/Frameworks/Infrastructure/Business/Presentation/MyBaseMVControllerCore.cs b/root/programs/Frameworks/Infrastructure/Business/Presentation/MyBaseMVControllerCore.cs new file mode 100644 index 00000000..860f5e15 --- /dev/null +++ b/root/programs/Frameworks/Infrastructure/Business/Presentation/MyBaseMVControllerCore.cs @@ -0,0 +1,320 @@ +//********************************************************************************** +//* Copyright (C) 2007,2016 Hitachi Solutions,Ltd. +//********************************************************************************** + +#region Apache License +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#endregion + +//********************************************************************************** +//* クラス名 :MyBaseMVControllerCore +//* クラス日本語名 :ASP.NET MVC Core用 画面コード親クラス2(テンプレート) +//* +//* 作成者 :生技 西野 +//* 更新履歴 : +//* +//* 日時 更新者 内容 +//* ---------- ---------------- ------------------------------------------------- +//* 2018/04/19 西野 大介 新規作成 +//* 2018/07/19 西野 大介 復元後のユーザー情報をSessionに設定するコードを追加 +//* 2018/08/08 西野 大介 MyMVCCoreFilterAttributeをFilterAttributeとして設定 +//********************************************************************************** + +using System; +using System.Threading.Tasks; + +using Microsoft.AspNetCore.Routing; +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Authentication.Cookies; +using Microsoft.AspNetCore.Mvc.Filters; +using Microsoft.Extensions.Primitives; + +using Touryo.Infrastructure.Business.Util; +using Touryo.Infrastructure.Framework.StdMigration; +using Touryo.Infrastructure.Framework.Presentation; +using Touryo.Infrastructure.Framework.Exceptions; +using Touryo.Infrastructure.Framework.Util; +using Touryo.Infrastructure.Public.Log; +using Touryo.Infrastructure.Public.Util; + +#region イベント実行順 +// お楽しみはこれからだ!: イベントの実行順が面白くて +// http://takepara.blogspot.jp/2008/08/blog-post.html +// +// before Execute +// +// - OnAuthorization +// +// - OnActionExecuting +// -- Index action execute ← ここでアクション実行 +// -- View +// - OnActionExecuted +// +// - OnResultExecuting +// -- page rendering ← ここでレンダリング +// - OnResultExecuted +// +// after Execute +#endregion + +namespace Touryo.Infrastructure.Business.Presentation +{ + /// 画面コード親クラス2 + /// (オーバーライドして)自由に利用できる。 + [MyMVCCoreFilter()] + public class MyBaseMVControllerCore : BaseMVControllerCore + { + /// 性能測定 + private PerformanceRecorder perfRec; + + /// UserInfo + protected MyUserInfo UserInfo; + + #region OnAction + + ///// + ///// アクション メソッドの呼び出し前に呼び出されます。 + ///// Controller.OnActionExecuting メソッド (Microsoft.AspNetCore.Mvc) + ///// https://docs.microsoft.com/ja-jp/dotnet/api/microsoft.aspnetcore.mvc.controller.onactionexecuting + ///// + ///// + ///// 型: Microsoft.AspNetCore.Mvc.Filters.ActionExecutingContext + ///// 現在の要求およびアクションに関する情報。 + ///// + //public override void OnActionExecuting(ActionExecutingContext filterContext) + //{ + // // OnActionExecutionAsyncに移行 + //} + + ///// + ///// アクション メソッドの呼び出し後に呼び出されます。 + ///// Controller.OnActionExecuted メソッド (Microsoft.AspNetCore.Mvc) + ///// https://docs.microsoft.com/ja-jp/dotnet/api/microsoft.aspnetcore.mvc.controller.onActionexecuted + ///// + ///// + ///// 型: Microsoft.AspNetCore.Mvc.Filters.ActionExecutedContext + ///// 現在の要求およびアクションに関する情報。 + ///// + //public override void OnActionExecuted(ActionExecutedContext filterContext) + //{ + // // OnActionExecutionAsyncに移行 + //} + + /// + /// Controller.OnActionExecutionAsync メソッド (Microsoft.AspNetCore.Mvc) + /// https://docs.microsoft.com/ja-jp/dotnet/api/microsoft.aspnetcore.mvc.controller.onactionexecutionasync + /// + /// Filters.ActionExecutedContext + /// ActionExecutionDelegate + /// Task + public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) + { + // 性能測定 + this.perfRec = null; + string strLogMessage = ""; + + #region OnActionExecuting に相当する処理 + + this.GetRouteData(context.RouteData); + + // カスタム認証処理 -------------------------------------------- + // ・・・ + // ------------------------------------------------------------- + + // 認証ユーザ情報をメンバにロードする -------------------------- + await this.GetUserInfo(); + // ------------------------------------------------------------- + + // 権限チェック ------------------------------------------------ + // ・・・ + // ------------------------------------------------------------- + + // 閉塞チェック ------------------------------------------------ + // ・・・ + // ------------------------------------------------------------- + + // キャッシュ制御処理 ------------------------------------------ + this.CacheControlWithSwitch(); + // ------------------------------------------------------------- + + // 性能測定開始 + this.perfRec = new PerformanceRecorder(); + this.perfRec.StartsPerformanceRecord(); + + // ------------ + // メッセージ部 + // ------------ + // ユーザ名, IPアドレス, + // レイヤ, 画面名, コントロール名, 処理名 + // 処理時間(実行時間), 処理時間(CPU時間) + // エラーメッセージID, エラーメッセージ等 + // ------------ + strLogMessage = + "," + this.UserInfo.UserName + + "," + this.UserInfo.IPAddress + + "," + "----->" + + "," + this.ControllerName + + "," + this.ActionName + "(OnActionExecuting)"; + + LogIF.InfoLog("ACCESS", strLogMessage); + + #endregion + + await base.OnActionExecutionAsync(context, next); + + #region OnActionExecuted に相当する処理 + + // 性能測定終了 + this.perfRec.EndsPerformanceRecord(); + + // ------------ + // メッセージ部 + // ------------ + // ユーザ名, IPアドレス, + // レイヤ, 画面名, コントロール名, 処理名 + // 処理時間(実行時間), 処理時間(CPU時間) + // エラーメッセージID, エラーメッセージ等 + // ------------ + strLogMessage = + "," + this.UserInfo.UserName + + "," + this.UserInfo.IPAddress + + "," + "<-----" + + "," + this.ControllerName + + "," + this.ActionName + "(OnActionExecuted)" + + "," + perfRec.ExecTime + + "," + perfRec.CpuTime; + + LogIF.InfoLog("ACCESS", strLogMessage); + + #endregion + } + + #endregion + + #region 情報取得用 + + /// ユーザ情報を取得する + private async Task GetUserInfo() + { + // セッションステートレス対応 + if (MyHttpContext.Current.Session == null) + { + // SessionがOFFの場合 + } + else + { + // 取得を試みる。 + this.UserInfo = UserInfoHandle.GetUserInformation(); + + // nullチェック + if (this.UserInfo == null) + { + AuthenticateResult authenticateInfo = + await AuthenticationHttpContextExtensions.AuthenticateAsync( + MyHttpContext.Current, CookieAuthenticationDefaults.AuthenticationScheme); + + //await MyHttpContext.Current.Authentication.GetAuthenticateInfoAsync( + // CookieAuthenticationDefaults.AuthenticationScheme); // 古い + + //System.Threading.Thread.CurrentPrincipal.Identity.Name; // .NET Framework + + string userName = authenticateInfo.Principal?.Identity?.Name; // null 条件演算子 + + if (string.IsNullOrEmpty(userName)) + { + // 未認証状態 + this.UserInfo = new MyUserInfo("未認証", (new GetClientIpAddress()).GetAddress()); + } + else + { + // 認証状態 + this.UserInfo = new MyUserInfo(userName, (new GetClientIpAddress()).GetAddress()); + + // 必要に応じて認証チケットのユーザ名からユーザ情報を復元する。 + // ★ 必要であれば、他の業務共通引継ぎ情報などをロードする。 + // ・・・ + + // 復元したユーザ情報をセット + UserInfoHandle.SetUserInformation(this.UserInfo); + } + } + } + } + + /// ルーティング情報を取得する + /// RouteData + private void GetRouteData(RouteData routeData) + { + string[] temp = null; + temp = routeData.Values["controller"].ToString().Split('.'); + this.ControllerName = routeData.Values["controller"].ToString(); + this.ActionName = routeData.Values["action"].ToString(); + } + + /// キャッシュ制御処理(スイッチ付き) + private void CacheControlWithSwitch() + { + // システムで固定に出来る場合は、ここでキャッシュ無効化する。 + // また、ユーザープログラムのファイル・ダウンロード処理などで + // フレームワークの設定したキャッシュ制御を変更したい場合は、Response.Clearを実行して再設定する。 + + // 画面遷移方法の定義を取得 + string noCache = GetConfigParameter.GetConfigValue(MyLiteral.CACHE_CONTROL); + + // デフォルト値対策:設定なし(null)の場合の扱いを決定 + if (noCache == null) + { + // OFF扱い + noCache = FxLiteral.OFF; + } + + if (noCache.ToUpper() == FxLiteral.ON) + { + // ON + + // http - How to control web page caching, across all browsers? - Stack Overflow + // http://stackoverflow.com/questions/49547/how-to-control-web-page-caching-across-all-browsers + + // IPA ISEC セキュア・プログラミング講座:Webアプリケーション編 第5章 暴露対策:プロキシキャッシュ対策 + // https://www.ipa.go.jp/security/awareness/vendor/programmingv2/contents/405.html + + // Using ASP.NET-MVC: + //this.Response.Cache.SetCacheability(HttpCacheability.NoCache); // HTTP 1.1. + //this.Response.Cache.AppendCacheExtension("no-store, must-revalidate"); + MyHttpContext.Current.Response.Headers.Add("Cache-Control", + new StringValues(new string[] { "no-cache", "no-store", "must-revalidate" })); + + //this.Response.AppendHeader("Pragma", "no-cache"); // HTTP 1.0. + MyHttpContext.Current.Response.Headers.Add("Pragma", new StringValues("no-cache")); + //this.Response.AppendHeader("Expires", "0"); // Proxies. + MyHttpContext.Current.Response.Headers.Add("Expires", new StringValues("0")); + } + else if (noCache.ToUpper() == FxLiteral.OFF) + { + // OFF + } + else + { + // パラメータ・エラー(書式不正) + throw new FrameworkException( + FrameworkExceptionMessage.ERROR_IN_WRITING_OF_FX_SWITCH1[0], + String.Format(FrameworkExceptionMessage.ERROR_IN_WRITING_OF_FX_SWITCH1[1], + MyLiteral.CACHE_CONTROL)); + } + } + + #endregion + } +} diff --git a/root/programs/Frameworks/Infrastructure/Business/Presentation/MyMVCCoreFilterAttribute.cs b/root/programs/Frameworks/Infrastructure/Business/Presentation/MyMVCCoreFilterAttribute.cs new file mode 100644 index 00000000..dd76d0af --- /dev/null +++ b/root/programs/Frameworks/Infrastructure/Business/Presentation/MyMVCCoreFilterAttribute.cs @@ -0,0 +1,282 @@ +//********************************************************************************** +//* Copyright (C) 2007,2016 Hitachi Solutions,Ltd. +//********************************************************************************** + +#region Apache License +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#endregion + +//********************************************************************************** +//* クラス名 :MyMVCCoreFilterAttribute +//* クラス日本語名 :ASP.NET MVC Core用 画面コード親クラス2相当(テンプレート) +//* +//* 作成者 :生技 西野 +//* 更新履歴 : +//* +//* 日時 更新者 内容 +//* ---------- ---------------- ------------------------------------------------- +//* 2018/08/08 西野 大介 新規作成 +//********************************************************************************** + +using System; +using System.Linq; +using System.Collections.Generic; +using System.Threading.Tasks; + +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Routing; +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Authentication.Cookies; +using Microsoft.AspNetCore.Mvc.Filters; + +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +using Touryo.Infrastructure.Business.Util; +using Touryo.Infrastructure.Framework.StdMigration; +using Touryo.Infrastructure.Framework.Exceptions; +using Touryo.Infrastructure.Framework.Util; +using Touryo.Infrastructure.Public.Log; +using Touryo.Infrastructure.Public.Util; + +namespace Touryo.Infrastructure.Business.Presentation +{ + /// 非同期 ASP.NET WebAPI用 ベーククラス2 + /// (ActionFilterAttributeとして)自由に利用できる。 + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)] + public class MyMVCCoreFilterAttribute : ActionFilterAttribute, IExceptionFilter + { + /// UserInfo + protected MyUserInfo UserInfo; + + /// ControllerName + protected string ControllerName = ""; + + /// ActionName + protected string ActionName = ""; + + #region OnException + + /// + /// 非同期の例外フィルターを実行します。 + /// https://msdn.microsoft.com/ja-jp/library/hh835353.aspx + /// + /// HttpActionExecutedContext + public void OnException(ExceptionContext exceptionContext) + { + //// Calling base class method. + //base.OnException(exceptionContext); + // エラーログの出力 + this.OutputErrorLog(exceptionContext); + // エラー画面に画面遷移する + this.TransferErrorScreen(exceptionContext); + } + + /// エラーログの出力 + /// ExceptionContext + private void OutputErrorLog(ExceptionContext exceptionContext) + { + this.GetRouteData(exceptionContext.RouteData); + this.GetUserInfo(); // 同期実行(待機 + + // 非同期ControllerのInnerException対策(底のExceptionを取得する)。 + Exception ex = exceptionContext.Exception; + Exception bottomException = ex; + while (bottomException.InnerException != null) + { + bottomException = bottomException.InnerException; + } + + // ------------ + // メッセージ部 + // ------------ + // ユーザ名, IPアドレス, + // レイヤ, 画面名, コントロール名, 処理名 + // 処理時間(実行時間), 処理時間(CPU時間) + // エラーメッセージID, エラーメッセージ等 + // ------------ + + string strLogMessage = + "," + (this.UserInfo != null ? this.UserInfo.UserName : "null") + + "," + (this.UserInfo != null ? this.UserInfo.IPAddress : "null") + + "," + "<-----" + + "," + this.ControllerName + + "," + this.ActionName + "(OnException)" + + "," + //this.perfRec.ExecTime + + "," + //this.perfRec.CpuTime + + "," + GetExceptionMessageID(bottomException) + + "," + bottomException.Message + "\r\n" + + "," + bottomException.StackTrace + "\r\n" + + "," + ex.ToString(); // Exception.ToString()はRootのExceptionに対して行なう。 + + LogIF.ErrorLog("ACCESS", strLogMessage); + } + + /// 例外発生時に、エラー画面に画面遷移 + /// ExceptionContext + private void TransferErrorScreen(ExceptionContext exceptionContext) + { + exceptionContext.ExceptionHandled = true; + + // Development、Staging、Production + string tmp = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT"); + if (string.IsNullOrEmpty(tmp)) + { + // Production + } + if (tmp.ToUpper() != "Development".ToUpper()) + { + // Staging or Production + } + else + { + // Development + + // 開発時は、app.UseDeveloperExceptionPage(); を使用するため。 + exceptionContext.ExceptionHandled = false; + return; // 何もしないで戻る。 + } + + // 非同期ControllerのInnerException対策(底のExceptionを取得する)。 + Exception ex = exceptionContext.Exception; + Exception bottomException = ex; + while (bottomException.InnerException != null) + { + bottomException = bottomException.InnerException; + } + + #region 例外型を判別しエラーメッセージIDを取得 + + // エラー画面へのパスを取得 --- チェック不要(ベースクラスでチェック済み) + string errorScreenPath = GetConfigParameter.GetConfigValue(FxLiteral.ERROR_SCREEN_PATH); + + // エラーメッセージID + string errMsgId = this.GetExceptionMessageID(ex); + + #endregion + + #region エラー時に、セッションを開放しないで、業務を続行可能にする処理を追加。 + + ISession session = MyHttpContext.Current.Session; + + // 不正操作エラー or 画面遷移制御チェック エラー + if (errMsgId == "IllegalOperationCheckError" + || errMsgId == "ScreenControlCheckError") + { + // セッションをクリアしない + session.SetInt32(FxHttpContextIndex.SESSION_ABANDON_FLAG, Convert.ToInt32(false)); + } + else + { + // セッションをクリアする + session.SetInt32(FxHttpContextIndex.SESSION_ABANDON_FLAG, Convert.ToInt32(true)); + } + + #endregion + + // エラー画面へ遷移 + exceptionContext.HttpContext.Response.Redirect(errorScreenPath); + } + + /// ExceptionのMessageIDを返す。 + /// Exception + /// ExceptionのMessageID + private string GetExceptionMessageID(Exception ex) + { + // Check exception type + if (ex is BusinessSystemException) + { + // システム例外 + BusinessSystemException bsEx = (BusinessSystemException)ex; + return bsEx.messageID; + } + else if (ex is FrameworkException) + { + // フレームワーク例外 + FrameworkException fxEx = (FrameworkException)ex; + return fxEx.messageID; + } + else + { + // それ以外の例外 + return "other Exception"; + } + } + + #endregion + + #region 情報取得用 + + /// ユーザ情報を取得する + private async Task GetUserInfo() + { + // セッションステートレス対応 + if (MyHttpContext.Current.Session == null) + { + // SessionがOFFの場合 + } + else + { + // 取得を試みる。 + this.UserInfo = UserInfoHandle.GetUserInformation(); + + // nullチェック + if (this.UserInfo == null) + { + AuthenticateResult authenticateInfo = + await AuthenticationHttpContextExtensions.AuthenticateAsync( + MyHttpContext.Current, CookieAuthenticationDefaults.AuthenticationScheme); + + //await MyHttpContext.Current.Authentication.GetAuthenticateInfoAsync( + // CookieAuthenticationDefaults.AuthenticationScheme); // 古い + + //System.Threading.Thread.CurrentPrincipal.Identity.Name; // .NET Framework + + string userName = authenticateInfo.Principal?.Identity?.Name; // null 条件演算子 + + if (string.IsNullOrEmpty(userName)) + { + // 未認証状態 + this.UserInfo = new MyUserInfo("未認証", (new GetClientIpAddress()).GetAddress()); + } + else + { + // 認証状態 + this.UserInfo = new MyUserInfo(userName, (new GetClientIpAddress()).GetAddress()); + + // 必要に応じて認証チケットのユーザ名からユーザ情報を復元する。 + // ★ 必要であれば、他の業務共通引継ぎ情報などをロードする。 + // ・・・ + + // 復元したユーザ情報をセット + UserInfoHandle.SetUserInformation(this.UserInfo); + } + } + } + } + + /// ルーティング情報を取得する + /// RouteData + private void GetRouteData(RouteData routeData) + { + string[] temp = null; + temp = routeData.Values["controller"].ToString().Split('.'); + this.ControllerName = routeData.Values["controller"].ToString(); + this.ActionName = routeData.Values["action"].ToString(); + } + + #endregion + } +} diff --git a/root/programs/Frameworks/Infrastructure/Business/Util/MyCmnFunction.cs b/root/programs/Frameworks/Infrastructure/Business/Util/MyCmnFunction.cs index c5432151..5d6b56f9 100644 --- a/root/programs/Frameworks/Infrastructure/Business/Util/MyCmnFunction.cs +++ b/root/programs/Frameworks/Infrastructure/Business/Util/MyCmnFunction.cs @@ -38,19 +38,26 @@ //* 2012/06/14 西野 大介 コントロール検索の再帰処理性能の集約&効率化。 //* 2014/05/16 西野 大介 キャスト可否チェックのロジックを見直した。 //* 2017/01/31 西野 大介 System.Webを使用しているCalculateSessionSizeメソッドをPublicから移動 +//* 2018/03/29 西野 大介 .NET Standard対応で、削除機能に関連するメソッドを削除 +//* 2018/03/29 西野 大介 .NET Standard対応で、HttpSessionのポーティング //********************************************************************************** using System; using System.Collections.Generic; -using System.Web; -using System.Web.UI; -using System.Web.UI.WebControls; - using Touryo.Infrastructure.Framework.Util; using Touryo.Infrastructure.Public.IO; using Touryo.Infrastructure.Public.Util; +#if NETCOREAPP2_0 +using Touryo.Infrastructure.Framework.StdMigration; +using Microsoft.AspNetCore.Http; +#else +using System.Web; +using System.Web.UI; +using System.Web.UI.WebControls; +#endif + namespace Touryo.Infrastructure.Business.Util { /// Business層の共通クラス @@ -85,12 +92,19 @@ public static long CalculateSessionSize() long size = 0; // SessionのオブジェクトをBinarySerializeしてサイズを取得。 +#if NETCOREAPP2_0 + foreach (string key in MyHttpContext.Current.Session.Keys) + { + // 当該キーのオブジェクト・サイズを足しこむ。 + size += BinarySerialize.ObjectToBytes(MyHttpContext.Current.Session.GetString(key)).Length; + } +#else foreach (string key in HttpContext.Current.Session.Keys) { // 当該キーのオブジェクト・サイズを足しこむ。 size += BinarySerialize.ObjectToBytes(HttpContext.Current.Session[key]).Length; } - +#endif // Sessionサイズ(バイト) return size; } @@ -101,6 +115,8 @@ public static long CalculateSessionSize() #region コントロール取得&イベントハンドラ設定 +#if NETCOREAPP2_0 +#else /// コントロール取得&イベントハンドラ設定(下位互換) /// コントロール /// プレフィックス @@ -261,8 +277,8 @@ internal static void GetCtrlAndSetClickEventHandler2( } #endregion - } - + } +#endif #endregion // 2009/07/21-end diff --git a/root/programs/Frameworks/Infrastructure/Business/app.config b/root/programs/Frameworks/Infrastructure/Business/app.config index 8f2c8ee3..dde2c3cc 100644 --- a/root/programs/Frameworks/Infrastructure/Business/app.config +++ b/root/programs/Frameworks/Infrastructure/Business/app.config @@ -6,11 +6,6 @@ - - - - - \ No newline at end of file diff --git a/root/programs/Frameworks/Infrastructure/Business/packages.config b/root/programs/Frameworks/Infrastructure/Business/packages.config index 52e01b53..9ae6d8e2 100644 --- a/root/programs/Frameworks/Infrastructure/Business/packages.config +++ b/root/programs/Frameworks/Infrastructure/Business/packages.config @@ -8,16 +8,17 @@ + - + - - - - - + + + + + \ No newline at end of file diff --git a/root/programs/MultiPurposeAuthSite/CreateJwkSetJson/App.config b/root/programs/MultiPurposeAuthSite/CreateJwkSetJson/App.config new file mode 100644 index 00000000..490b34dd --- /dev/null +++ b/root/programs/MultiPurposeAuthSite/CreateJwkSetJson/App.config @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/root/programs/MultiPurposeAuthSite/CreateJwkSetJson/CreateJwkSetJson.csproj b/root/programs/MultiPurposeAuthSite/CreateJwkSetJson/CreateJwkSetJson.csproj new file mode 100644 index 00000000..c1f6bf65 --- /dev/null +++ b/root/programs/MultiPurposeAuthSite/CreateJwkSetJson/CreateJwkSetJson.csproj @@ -0,0 +1,71 @@ + + + + + Debug + AnyCPU + {5E268E70-CCCC-4629-A442-F077FAB243A1} + Exe + Properties + CreateJwkSetJson + CreateJwkSetJson + v4.6 + 512 + true + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\packages\Newtonsoft.Json.11.0.1\lib\net45\Newtonsoft.Json.dll + True + + + ..\..\Frameworks\Infrastructure\Build\OpenTouryo.Framework.dll + + + ..\..\Frameworks\Infrastructure\Build\OpenTouryo.Public.dll + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/root/programs/MultiPurposeAuthSite/CreateJwkSetJson/Program.cs b/root/programs/MultiPurposeAuthSite/CreateJwkSetJson/Program.cs new file mode 100644 index 00000000..1b9d1ce3 --- /dev/null +++ b/root/programs/MultiPurposeAuthSite/CreateJwkSetJson/Program.cs @@ -0,0 +1,90 @@ +//********************************************************************************** +//* Copyright (C) 2017 Hitachi Solutions,Ltd. +//********************************************************************************** + +#region Apache License +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#endregion + +//********************************************************************************** +//* クラス名 :CreateJwkSetJson +//* クラス日本語名 :JWKSetJson情報の生成ツール(ライブラリ) +//* +//* 作成日時 :- +//* 作成者 :- +//* 更新履歴 :- +//* +//* 日時 更新者 内容 +//* ---------- ---------------- ------------------------------------------------- +//* 2018/08/15 西野 大介 新規 +//********************************************************************************** + +using System.IO; +using System.Text; +using System.Collections.Generic; + +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +using Touryo.Infrastructure.Framework.Authentication; +using Touryo.Infrastructure.Public.Security; +using Touryo.Infrastructure.Public.IO; +using Touryo.Infrastructure.Public.Str; + +namespace CreateJwkSetJson +{ + class Program + { + static void Main(string[] args) + { + // 現在の証明書のJwk + JObject jwkObject = + JsonConvert.DeserializeObject( + RS256_KeyConverter.X509CerToJwkPublicKey(OAuth2AndOIDCParams.RS256Cer)); + + // JwkSet.jsonファイルの存在チェック + if (!ResourceLoader.Exists(OAuth2AndOIDCParams.JwkSetFilePath, false)) + { + // 新規 + File.Create(OAuth2AndOIDCParams.JwkSetFilePath).Close(); + } + else + { + // 既存? + } + + // JwkSet.jsonファイルのロード + JwkSet jwkSetObject = JwkSet.LoadJwkSet(OAuth2AndOIDCParams.JwkSetFilePath); + + // 判定 + if (jwkSetObject == null) + { + // 新規 + jwkSetObject = new JwkSet(); + jwkSetObject.keys.Add(jwkObject); + } + else + { + // 既存 + + // kidの重複確認 + JwkSet.AddJwkToJwkSet(jwkSetObject, jwkObject); + } + + // jwkSetObjectのセーブ + JwkSet.SaveJwkSet(OAuth2AndOIDCParams.JwkSetFilePath, jwkSetObject); + } + } +} diff --git a/root/programs/MultiPurposeAuthSite/CreateJwkSetJson/Properties/AssemblyInfo.cs b/root/programs/MultiPurposeAuthSite/CreateJwkSetJson/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..7a77d284 --- /dev/null +++ b/root/programs/MultiPurposeAuthSite/CreateJwkSetJson/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// アセンブリに関する一般情報は以下の属性セットをとおして制御されます。 +// アセンブリに関連付けられている情報を変更するには、 +// これらの属性値を変更してください。 +[assembly: AssemblyTitle("CreateJwkSetJson")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("CreateJwkSetJson")] +[assembly: AssemblyCopyright("Copyright © 2018")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// ComVisible を false に設定すると、その型はこのアセンブリ内で COM コンポーネントから +// 参照不可能になります。COM からこのアセンブリ内の型にアクセスする場合は、 +// その型の ComVisible 属性を true に設定してください。 +[assembly: ComVisible(false)] + +// このプロジェクトが COM に公開される場合、次の GUID が typelib の ID になります +[assembly: Guid("5e268e70-cccc-4629-a442-f077fab243a1")] + +// アセンブリのバージョン情報は次の 4 つの値で構成されています: +// +// メジャー バージョン +// マイナー バージョン +// ビルド番号 +// Revision +// +// すべての値を指定するか、下のように '*' を使ってビルドおよびリビジョン番号を +// 既定値にすることができます: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/root/programs/MultiPurposeAuthSite/CreateJwkSetJson/packages.config b/root/programs/MultiPurposeAuthSite/CreateJwkSetJson/packages.config new file mode 100644 index 00000000..bac0709b --- /dev/null +++ b/root/programs/MultiPurposeAuthSite/CreateJwkSetJson/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/root/programs/MultiPurposeAuthSite/CreateJwtBearerTokenFlowAssertion/App.config b/root/programs/MultiPurposeAuthSite/CreateJwtBearerTokenFlowAssertion/App.config index 3d7f7ebc..9c5566f2 100644 --- a/root/programs/MultiPurposeAuthSite/CreateJwtBearerTokenFlowAssertion/App.config +++ b/root/programs/MultiPurposeAuthSite/CreateJwtBearerTokenFlowAssertion/App.config @@ -1,8 +1,8 @@  - - + + diff --git a/root/programs/MultiPurposeAuthSite/CreateJwtBearerTokenFlowAssertion/Program.cs b/root/programs/MultiPurposeAuthSite/CreateJwtBearerTokenFlowAssertion/Program.cs index e05fba62..25774062 100644 --- a/root/programs/MultiPurposeAuthSite/CreateJwtBearerTokenFlowAssertion/Program.cs +++ b/root/programs/MultiPurposeAuthSite/CreateJwtBearerTokenFlowAssertion/Program.cs @@ -33,13 +33,11 @@ using System; -using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Touryo.Infrastructure.Framework.Authentication; using Touryo.Infrastructure.Public.Security; using Touryo.Infrastructure.Public.Str; -using Touryo.Infrastructure.Public.Util; namespace CreateJwtBearerTokenFlowAssertion { @@ -47,34 +45,35 @@ class Program { static void Main(string[] args) { - string iss = GetConfigParameter.GetConfigValue("iss"); - string aud = GetConfigParameter.GetConfigValue("aud"); + string iss = OAuth2AndOIDCParams.Isser; + string aud = OAuth2AndOIDCParams.Audience; + string scopes = "hoge1 hoge2 hoge3"; JObject jobj = null; - JWT_RS256_XML jwt_RS256 = new JWT_RS256_XML(); + JWS_RS256_XML jws_RS256 = new JWS_RS256_XML(); Console.WriteLine("PrivateKey:"); Console.WriteLine(CustomEncode.ToBase64String( - CustomEncode.StringToByte(jwt_RS256.XMLPrivateKey, CustomEncode.us_ascii))); + CustomEncode.StringToByte(jws_RS256.XMLPrivateKey, CustomEncode.us_ascii))); Console.WriteLine(""); Console.WriteLine("PublicKey:"); Console.WriteLine(CustomEncode.ToBase64String( - CustomEncode.StringToByte(jwt_RS256.XMLPublicKey, CustomEncode.us_ascii))); + CustomEncode.StringToByte(jws_RS256.XMLPublicKey, CustomEncode.us_ascii))); Console.WriteLine(""); string jwtAssertion = JwtAssertion.CreateJwtBearerTokenFlowAssertion( - GetConfigParameter.GetConfigValue("iss"), - GetConfigParameter.GetConfigValue("aud"), - new System.TimeSpan(0, 30, 0), scopes, - jwt_RS256.XMLPrivateKey); + OAuth2AndOIDCParams.Isser, + OAuth2AndOIDCParams.Audience, + new System.TimeSpan(0, 30, 0), scopes, + jws_RS256.XMLPrivateKey); if (JwtAssertion.VerifyJwtBearerTokenFlowAssertion( - jwtAssertion, out iss, out aud, out scopes, out jobj, jwt_RS256.XMLPublicKey)) + jwtAssertion, out iss, out aud, out scopes, out jobj, jws_RS256.XMLPublicKey)) { - if (iss == GetConfigParameter.GetConfigValue("iss") - && aud == GetConfigParameter.GetConfigValue("aud")) + if (iss == OAuth2AndOIDCParams.Isser + && aud == OAuth2AndOIDCParams.Audience) { Console.WriteLine("JwtAssertion:"); Console.WriteLine(jwtAssertion); diff --git a/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite.sln b/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite.sln index d904d252..ae6f8cd6 100644 --- a/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite.sln +++ b/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite.sln @@ -5,10 +5,6 @@ VisualStudioVersion = 14.0.25420.1 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MultiPurposeAuthSite", "MultiPurposeAuthSite\MultiPurposeAuthSite.csproj", "{4BA4D9DE-2656-4FBD-8F1F-31FC9583B5F5}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CreateClientsIdentity", "CreateClientsIdentity\CreateClientsIdentity.csproj", "{9176504B-F14B-4C59-8601-5C04BE9A889D}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CreateJwtBearerTokenFlowAssertion", "CreateJwtBearerTokenFlowAssertion\CreateJwtBearerTokenFlowAssertion.csproj", "{4AB3D69C-314D-4CF2-8A3A-F8E1536BFA3F}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -25,24 +21,11 @@ Global {4BA4D9DE-2656-4FBD-8F1F-31FC9583B5F5}.Release|Any CPU.Build.0 = Release|Any CPU {4BA4D9DE-2656-4FBD-8F1F-31FC9583B5F5}.Release|x86.ActiveCfg = Release|Any CPU {4BA4D9DE-2656-4FBD-8F1F-31FC9583B5F5}.Release|x86.Build.0 = Release|Any CPU - {9176504B-F14B-4C59-8601-5C04BE9A889D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9176504B-F14B-4C59-8601-5C04BE9A889D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9176504B-F14B-4C59-8601-5C04BE9A889D}.Debug|x86.ActiveCfg = Debug|Any CPU - {9176504B-F14B-4C59-8601-5C04BE9A889D}.Debug|x86.Build.0 = Debug|Any CPU - {9176504B-F14B-4C59-8601-5C04BE9A889D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9176504B-F14B-4C59-8601-5C04BE9A889D}.Release|Any CPU.Build.0 = Release|Any CPU - {9176504B-F14B-4C59-8601-5C04BE9A889D}.Release|x86.ActiveCfg = Release|Any CPU - {9176504B-F14B-4C59-8601-5C04BE9A889D}.Release|x86.Build.0 = Release|Any CPU - {4AB3D69C-314D-4CF2-8A3A-F8E1536BFA3F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4AB3D69C-314D-4CF2-8A3A-F8E1536BFA3F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4AB3D69C-314D-4CF2-8A3A-F8E1536BFA3F}.Debug|x86.ActiveCfg = Debug|Any CPU - {4AB3D69C-314D-4CF2-8A3A-F8E1536BFA3F}.Debug|x86.Build.0 = Debug|Any CPU - {4AB3D69C-314D-4CF2-8A3A-F8E1536BFA3F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4AB3D69C-314D-4CF2-8A3A-F8E1536BFA3F}.Release|Any CPU.Build.0 = Release|Any CPU - {4AB3D69C-314D-4CF2-8A3A-F8E1536BFA3F}.Release|x86.ActiveCfg = Release|Any CPU - {4AB3D69C-314D-4CF2-8A3A-F8E1536BFA3F}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {D89D73D6-6E87-40F5-BE72-5D8120023347} + EndGlobalSection EndGlobal diff --git a/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/App_Start/WebApiConfig.cs b/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/App_Start/WebApiConfig.cs index b28c8aa7..6c07ec25 100644 --- a/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/App_Start/WebApiConfig.cs +++ b/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/App_Start/WebApiConfig.cs @@ -44,7 +44,9 @@ public static void Register(HttpConfiguration config) config.SuppressDefaultHostAuthentication(); config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType)); - // JSON データにはCamelCaseを使用 (JSON.NET) + // JSON を既定にして、CamelCaseを使用 (JSON.NET) + config.Formatters.Remove(config.Formatters.XmlFormatter); + config.Formatters.Add(config.Formatters.JsonFormatter); config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); // CORS (Cross-Origin Resource Sharing)の有効化 diff --git a/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Controllers/AccountController.cs b/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Controllers/AccountController.cs index 2ca936e3..e392574a 100644 --- a/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Controllers/AccountController.cs +++ b/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Controllers/AccountController.cs @@ -301,7 +301,7 @@ public async Task Login(AccountLoginViewModel model, string submit // Open-Redirect対策 if (!string.IsNullOrEmpty(model.ReturnUrl) - && GetConfigParameter.GetConfigValue("OAuthAuthorizationServerEndpointsRootURI").IndexOf(model.ReturnUrl) != 1) + && ASPNETIdentityConfig.OAuth2AuthorizationServerEndpointsRootURI.IndexOf(model.ReturnUrl) != 1) { return RedirectToLocal(model.ReturnUrl); } @@ -369,8 +369,8 @@ public async Task Login(AccountLoginViewModel model, string submit // 認可エンドポイント string oAuthAuthorizeEndpoint = - ASPNETIdentityConfig.OAuthAuthorizationServerEndpointsRootURI - + ASPNETIdentityConfig.OAuthAuthorizeEndpoint; + ASPNETIdentityConfig.OAuth2AuthorizationServerEndpointsRootURI + + ASPNETIdentityConfig.OAuth2AuthorizeEndpoint; // client_id string client_id = OAuth2AndOIDCParams.ClientID; @@ -482,7 +482,7 @@ public async Task Login(AccountLoginViewModel model, string submit // Open-Redirect対策 if (!string.IsNullOrEmpty(model.ReturnUrl) - && GetConfigParameter.GetConfigValue("OAuthAuthorizationServerEndpointsRootURI").IndexOf(model.ReturnUrl) != 1) + && ASPNETIdentityConfig.OAuth2AuthorizationServerEndpointsRootURI.IndexOf(model.ReturnUrl) != 1) { return RedirectToLocal(model.ReturnUrl); } @@ -1500,7 +1500,7 @@ public async Task ExternalLoginCallback(string returnUrl) ASPNETIdentityConfig.TwitterAuthenticationClientId, ASPNETIdentityConfig.TwitterAuthenticationClientSecret); - email = (string)myInfo["email"]; // Microsoft.Owin.Security.Twitterでは、emailClaimとして取得できない。 + email = (string)myInfo[OAuth2AndOIDCConst.Scope_Email]; // Microsoft.Owin.Security.Twitterでは、emailClaimとして取得できない。 emailClaim = new Claim(ClaimTypes.Email, email); // emailClaimとして生成 } } @@ -1753,7 +1753,7 @@ public async Task IDFederationRedirectEndPoint(string code, string { // 結果を格納する変数。 Dictionary dic = null; - OAuthAuthorizationCodeGrantClientViewModel model = new OAuthAuthorizationCodeGrantClientViewModel + OAuth2AuthorizationCodeGrantClientViewModel model = new OAuth2AuthorizationCodeGrantClientViewModel { State = state, Code = code @@ -1793,13 +1793,13 @@ public async Task IDFederationRedirectEndPoint(string code, string List scopes = null; JObject jobj = null; - if (dic.ContainsKey("id_token")) + if (dic.ContainsKey(OAuth2AndOIDCConst.IDToken)) { // id_tokenがある。 - string id_token = dic["id_token"]; + string id_token = dic[OAuth2AndOIDCConst.IDToken]; if (JwtToken.Verify(id_token, out sub, out roles, out scopes, out jobj) - && jobj["nonce"].ToString() == (string)Session["id_federation_signin_nonce"]) + && jobj[OAuth2AndOIDCConst.nonce].ToString() == (string)Session["id_federation_signin_nonce"]) { // id_token検証OK。 } @@ -1822,7 +1822,7 @@ public async Task IDFederationRedirectEndPoint(string code, string #region /userinfoエンドポイント //// /userinfoエンドポイントにアクセスする場合 //string response = await OAuth2AndOIDCClient.CallUserInfoEndpointAsync( - // new Uri(ASPNETIdentityConfig.IdFederationUserInfoEndPoint), dic["access_token"]); + // new Uri(ASPNETIdentityConfig.IdFederationUserInfoEndPoint), dic[OAuth2AndOIDCConst.AccessToken]); #endregion #region ユーザの登録・更新 @@ -1848,22 +1848,22 @@ public async Task IDFederationRedirectEndPoint(string code, string // } IdentityResult result = null; - ApplicationUser user = await UserManager.FindByIdAsync((string)jobj["userid"]); + ApplicationUser user = await UserManager.FindByIdAsync((string)jobj[OAuth2AndOIDCConst.Scope_UserID]); if (user == null) { // 新規作成 user = new ApplicationUser() { - Id = (string)jobj["userid"], + Id = (string)jobj[OAuth2AndOIDCConst.Scope_UserID], UserName = sub, - Email = (string)jobj["email"], - EmailConfirmed = (bool)Convert.ToBoolean((string)jobj["email_verified"]), + Email = (string)jobj[OAuth2AndOIDCConst.Scope_Email], + EmailConfirmed = (bool)Convert.ToBoolean((string)jobj[OAuth2AndOIDCConst.email_verified]), - PhoneNumber = (string)jobj["phone_number"], - PhoneNumberConfirmed = (bool)Convert.ToBoolean((string)jobj["phone_number_verified"]), + PhoneNumber = (string)jobj[OAuth2AndOIDCConst.phone_number], + PhoneNumberConfirmed = (bool)Convert.ToBoolean((string)jobj[OAuth2AndOIDCConst.phone_number_verified]), CreatedDate = DateTime.Now }; @@ -1881,11 +1881,11 @@ public async Task IDFederationRedirectEndPoint(string code, string // 属性更新 user.UserName = sub; - user.Email = (string)jobj["email"]; - user.EmailConfirmed = (bool)Convert.ToBoolean((string)jobj["email_verified"]); + user.Email = (string)jobj[OAuth2AndOIDCConst.Scope_Email]; + user.EmailConfirmed = (bool)Convert.ToBoolean((string)jobj[OAuth2AndOIDCConst.email_verified]); - user.PhoneNumber = (string)jobj["phone_number"]; - user.PhoneNumberConfirmed = (bool)Convert.ToBoolean((string)jobj["phone_number_verified"]); + user.PhoneNumber = (string)jobj[OAuth2AndOIDCConst.phone_number]; + user.PhoneNumberConfirmed = (bool)Convert.ToBoolean((string)jobj[OAuth2AndOIDCConst.phone_number_verified]); result = await UserManager.UpdateAsync(user); @@ -2000,7 +2000,7 @@ public async Task IDFederationRedirectEndPoint(string code, string /// ActionResultを非同期に返す /// [HttpGet] - public async Task OAuthAuthorize(string response_type, string client_id, string scope, string state, + public async Task OAuth2Authorize(string response_type, string client_id, string scope, string state, string nonce, string prompt, // OpenID Connect string code_challenge, string code_challenge_method) // OAuth PKCE { @@ -2012,14 +2012,14 @@ public async Task OAuthAuthorize(string response_type, string clie // scopeパラメタ string[] scopes = (scope ?? "").Split(' '); - if (response_type.ToLower() == ASPNETIdentityConst.AuthorizationCodeResponseType) + if (response_type.ToLower() == OAuth2AndOIDCConst.AuthorizationCodeResponseType) { // Authorization Codeグラント種別(仲介コードの発行) ViewBag.Name = identity.Name; ViewBag.Scopes = scopes; // 認証の場合、余計なscopeをfilterする。 - bool isAuth = scopes.Any(x => x.ToLower() == ASPNETIdentityConst.Scope_Auth); + bool isAuth = scopes.Any(x => x.ToLower() == OAuth2AndOIDCConst.Scope_Auth); if (string.IsNullOrWhiteSpace(prompt)) prompt = ""; @@ -2031,7 +2031,7 @@ public async Task OAuthAuthorize(string response_type, string clie // アクセス要求を保存して、仲介コードを発行する。 identity = new ClaimsIdentity(identity.Claims, OAuthDefaults.AuthenticationType, identity.NameClaimType, identity.RoleClaimType); - //ClaimsIdentity identity = new ClaimsIdentity(new ClaimsPrincipal(User).Claims.ToArray(), "Bearer"); + //ClaimsIdentity identity = new ClaimsIdentity(new ClaimsPrincipal(User).Claims.ToArray(), OAuth2AndOIDCConst.bearer); // ClaimsIdentityに、その他、所定のClaimを追加する。 // ただし、認可画面をスキップする場合は、scopeをフィルタする。 @@ -2059,11 +2059,11 @@ public async Task OAuthAuthorize(string response_type, string clie return View(); } } - else if ((response_type.ToLower() == ASPNETIdentityConst.ImplicitResponseType)) + else if ((response_type.ToLower() == OAuth2AndOIDCConst.ImplicitResponseType)) // OIDC Implicit Flowはresponse_type=tokenに書換、識別できないので、prompt=noneを設定。 { // Implicitグラント種別(Access Tokenの発行) - if (scopes.Any(x => x.ToLower() == ASPNETIdentityConst.Scope_Auth)) + if (scopes.Any(x => x.ToLower() == OAuth2AndOIDCConst.Scope_Auth)) { // authの場合、Implicitグラント種別はNGとする。 } @@ -2071,7 +2071,7 @@ public async Task OAuthAuthorize(string response_type, string clie { // アクセス要求の許可 identity = new ClaimsIdentity(identity.Claims, OAuthDefaults.AuthenticationType, identity.NameClaimType, identity.RoleClaimType); - //ClaimsIdentity identity = new ClaimsIdentity(new ClaimsPrincipal(User).Claims.ToArray(), "Bearer"); + //ClaimsIdentity identity = new ClaimsIdentity(new ClaimsPrincipal(User).Claims.ToArray(), OAuth2AndOIDCConst.bearer); // ClaimsIdentityに、その他、所定のClaimを追加する。 OAuth2Helper.AddClaim(identity, client_id, state, scopes, nonce); @@ -2110,7 +2110,7 @@ public async Task OAuthAuthorize(string response_type, string clie /// [HttpPost] [ValidateAntiForgeryToken] - public async Task OAuthAuthorize(string client_id, string scope, string state, string nonce) + public async Task OAuth2Authorize(string client_id, string scope, string state, string nonce) { // Cookie認証チケットからClaimsIdentityを取得しておく。 AuthenticateResult ticket = this.AuthenticationManager @@ -2133,7 +2133,7 @@ public async Task OAuthAuthorize(string client_id, string scope, s { // アクセス要求を保存して、仲介コードを発行する。 identity = new ClaimsIdentity(identity.Claims, OAuthDefaults.AuthenticationType, identity.NameClaimType, identity.RoleClaimType); - //ClaimsIdentity identity = new ClaimsIdentity(new ClaimsPrincipal(User).Claims.ToArray(), "Bearer"); + //ClaimsIdentity identity = new ClaimsIdentity(new ClaimsPrincipal(User).Claims.ToArray(), OAuth2AndOIDCConst.bearer); // ClaimsIdentityに、その他、所定のClaimを追加する。 OAuth2Helper.AddClaim(identity, client_id, state, scopes, nonce); @@ -2175,7 +2175,7 @@ public async Task OAuthAuthorize(string client_id, string scope, s /// /// [AllowAnonymous] - public async Task OAuthAuthorizationCodeGrantClient(string code, string state) + public async Task OAuth2AuthorizationCodeGrantClient(string code, string state) { #region テスト用 @@ -2186,6 +2186,13 @@ public async Task OAuthAuthorizationCodeGrantClient(string code, s state_InSessionOrCookie = Request.Cookies["test_state"].Value; } + // nonce + string nonce_InSessionOrCookie = (string)Session["test_nonce"]; + if (string.IsNullOrEmpty(nonce_InSessionOrCookie)) + { + nonce_InSessionOrCookie = Request.Cookies["test_nonce"].Value; + } + // code_verifier string code_verifier_InSessionOrCookie = (string)Session["test_code_verifier"]; if (string.IsNullOrEmpty(code_verifier_InSessionOrCookie)) @@ -2205,12 +2212,12 @@ public async Task OAuthAuthorizationCodeGrantClient(string code, s { // Tokenエンドポイントにアクセス Uri tokenEndpointUri = new Uri( - ASPNETIdentityConfig.OAuthAuthorizationServerEndpointsRootURI - + ASPNETIdentityConfig.OAuthBearerTokenEndpoint); + ASPNETIdentityConfig.OAuth2AuthorizationServerEndpointsRootURI + + ASPNETIdentityConfig.OAuth2BearerTokenEndpoint); // 結果を格納する変数。 Dictionary dic = null; - OAuthAuthorizationCodeGrantClientViewModel model = new OAuthAuthorizationCodeGrantClientViewModel + OAuth2AuthorizationCodeGrantClientViewModel model = new OAuth2AuthorizationCodeGrantClientViewModel { State = state, Code = code @@ -2221,41 +2228,112 @@ public async Task OAuthAuthorizationCodeGrantClient(string code, s string client_secret = OAuth2Helper.GetInstance().GetClientSecret(client_id); #region 仲介コードを使用してAccess Token・Refresh Tokenを取得 - + //stateの検証 - if (state == state_InSessionOrCookie) + if (state == state_InSessionOrCookie + || state == "fapi1:" + state_InSessionOrCookie) { //state正常 // 仲介コードからAccess Tokenを取得する。 string redirect_uri - = ASPNETIdentityConfig.OAuthClientEndpointsRootURI - + ASPNETIdentityConfig.OAuthAuthorizationCodeGrantClient_Account; + = ASPNETIdentityConfig.OAuth2ClientEndpointsRootURI + + ASPNETIdentityConfig.OAuth2AuthorizationCodeGrantClient_Account; // Tokenエンドポイントにアクセス - model.Response = await OAuth2Helper.GetInstance() - .GetAccessTokenByCodeAsync(tokenEndpointUri, client_id, client_secret, redirect_uri, code, code_verifier_InSessionOrCookie); + if (!state.StartsWith("fapi1:")) + { + if (string.IsNullOrEmpty(code_verifier_InSessionOrCookie)) + { + // 通常 + model.Response = await OAuth2Helper.GetInstance() + .GetAccessTokenByCodeAsync(tokenEndpointUri, client_id, client_secret, redirect_uri, code); + } + else + { + // PKCE + model.Response = await OAuth2Helper.GetInstance() + .GetAccessTokenByCodeAsync( + tokenEndpointUri, client_id, client_secret, redirect_uri, + code, code_verifier_InSessionOrCookie); + } + } + else + { + // FAPI1 + + // Tokenエンドポイントにアクセス + string aud = ASPNETIdentityConfig.OAuth2AuthorizationServerEndpointsRootURI + + ASPNETIdentityConfig.OAuth2BearerTokenEndpoint; + + // ClientNameから、client_id(iss)を取得。 + string iss = ""; + + // Client Accountのみ + iss = OAuth2Helper.GetInstance().GetClientIdByName("TestClient"); + + // テストなので秘密鍵は共通とする。 + string privateKey = OAuth2AndOIDCParams.OAuth2JwtAssertionPrivatekey; + privateKey = CustomEncode.ByteToString(CustomEncode.FromBase64String(privateKey), CustomEncode.us_ascii); + + model.Response = await OAuth2Helper.GetInstance().GetAccessTokenByCodeAsync( + tokenEndpointUri, redirect_uri, code, JwtAssertion.CreateJwtBearerTokenFlowAssertion( + iss, aud, new TimeSpan(0, 0, 30), ASPNETIdentityConst.StandardScopes, privateKey)); + } + dic = JsonConvert.DeserializeObject>(model.Response); - model.AccessToken = dic["access_token"]; + model.AccessToken = dic[OAuth2AndOIDCConst.AccessToken]; model.AccessTokenJwtToJson = CustomEncode.ByteToString( CustomEncode.FromBase64UrlString(model.AccessToken.Split('.')[1]), CustomEncode.UTF_8); // 余談:OpenID Connectであれば、ここで id_token 検証。 - if (dic.ContainsKey("id_token")) + if (dic.ContainsKey(OAuth2AndOIDCConst.IDToken)) { - model.IdToken = dic["id_token"]; + model.IdToken = dic[OAuth2AndOIDCConst.IDToken]; model.IdTokenJwtToJson = CustomEncode.ByteToString( CustomEncode.FromBase64UrlString(model.IdToken.Split('.')[1]), CustomEncode.UTF_8); } - model.RefreshToken = dic.ContainsKey("refresh_token") ? dic["refresh_token"] : ""; + model.RefreshToken = dic.ContainsKey(OAuth2AndOIDCConst.RefreshToken) ? dic[OAuth2AndOIDCConst.RefreshToken] : ""; } else { // state異常 } + #region 各種Token検証 + + string out_sub = ""; + JObject out_jobj = null; + + if (!string.IsNullOrEmpty(model.AccessToken)) + { + List out_roles = null; + List out_scopes = null; + + if (!JwtToken.Verify(model.AccessToken, + out out_sub, out out_roles, out out_scopes, out out_jobj)) + { + throw new Exception("AccessToken検証エラー"); + } + } + + if (!string.IsNullOrEmpty(model.IdToken)) + { + string out_nonce = ""; + + if(!IdToken.Verify(model.IdToken, + model.AccessToken, code, state, + out out_sub, out out_nonce, out out_jobj) + && out_nonce == nonce_InSessionOrCookie) + { + throw new Exception("IdToken検証エラー"); + } + } + + #endregion + #endregion // 画面の表示。 @@ -2263,6 +2341,7 @@ string redirect_uri } else { + // エラー return View("Error"); } } @@ -2278,7 +2357,7 @@ string redirect_uri [HttpPost] [AllowAnonymous] [ValidateAntiForgeryToken] - public async Task OAuthAuthorizationCodeGrantClient2(OAuthAuthorizationCodeGrantClientViewModel model) + public async Task OAuth2AuthorizationCodeGrantClient2(OAuth2AuthorizationCodeGrantClientViewModel model) { if (!ASPNETIdentityConfig.IsLockedDownRedirectEndpoint) { @@ -2298,8 +2377,8 @@ public async Task OAuthAuthorizationCodeGrantClient2(OAuthAuthoriz #region Tokenエンドポイントで、Refresh Tokenを使用してAccess Tokenを更新 Uri tokenEndpointUri = new Uri( - ASPNETIdentityConfig.OAuthAuthorizationServerEndpointsRootURI - + ASPNETIdentityConfig.OAuthBearerTokenEndpoint); + ASPNETIdentityConfig.OAuth2AuthorizationServerEndpointsRootURI + + ASPNETIdentityConfig.OAuth2BearerTokenEndpoint); // Tokenエンドポイントにアクセス @@ -2307,20 +2386,21 @@ public async Task OAuthAuthorizationCodeGrantClient2(OAuthAuthoriz string client_id = OAuth2Helper.GetInstance().GetClientIdByName("TestClient"); string client_secret = OAuth2Helper.GetInstance().GetClientSecret(client_id); - model.Response = await OAuth2Helper.GetInstance().UpdateAccessTokenByRefreshTokenAsync( + model.Response = await OAuth2Helper.GetInstance(). + UpdateAccessTokenByRefreshTokenAsync( tokenEndpointUri, client_id, client_secret, model.RefreshToken); dic = JsonConvert.DeserializeObject>(model.Response); - if (dic.ContainsKey("access_token")) + if (dic.ContainsKey(OAuth2AndOIDCConst.AccessToken)) { - model.AccessToken = dic["access_token"]; + model.AccessToken = dic[OAuth2AndOIDCConst.AccessToken]; model.AccessTokenJwtToJson = CustomEncode.ByteToString( CustomEncode.FromBase64UrlString(model.AccessToken.Split('.')[1]), CustomEncode.UTF_8); } - if (dic.ContainsKey("refresh_token")) + if (dic.ContainsKey(OAuth2AndOIDCConst.RefreshToken)) { - model.RefreshToken = dic["refresh_token"] ?? ""; + model.RefreshToken = dic[OAuth2AndOIDCConst.RefreshToken] ?? ""; } #endregion @@ -2337,18 +2417,18 @@ public async Task OAuthAuthorizationCodeGrantClient2(OAuthAuthoriz if (!string.IsNullOrEmpty(Request.Form.Get("submit.RevokeAccess"))) { token = model.AccessToken; - token_type_hint = "access_token"; + token_type_hint = OAuth2AndOIDCConst.AccessToken; } if (!string.IsNullOrEmpty(Request.Form.Get("submit.RevokeRefresh"))) { token = model.RefreshToken; - token_type_hint = "refresh_token"; + token_type_hint = OAuth2AndOIDCConst.RefreshToken; } Uri revokeTokenEndpointUri = new Uri( - ASPNETIdentityConfig.OAuthAuthorizationServerEndpointsRootURI - + ASPNETIdentityConfig.OAuthRevokeTokenWebAPI); + ASPNETIdentityConfig.OAuth2AuthorizationServerEndpointsRootURI + + ASPNETIdentityConfig.OAuth2RevokeTokenWebAPI); // Revokeエンドポイントにアクセス @@ -2373,18 +2453,18 @@ public async Task OAuthAuthorizationCodeGrantClient2(OAuthAuthoriz if (!string.IsNullOrEmpty(Request.Form.Get("submit.IntrospectAccess"))) { token = model.AccessToken; - token_type_hint = "access_token"; + token_type_hint = OAuth2AndOIDCConst.AccessToken; } if (!string.IsNullOrEmpty(Request.Form.Get("submit.IntrospectRefresh"))) { token = model.RefreshToken; - token_type_hint = "refresh_token"; + token_type_hint = OAuth2AndOIDCConst.RefreshToken; } Uri introspectTokenEndpointUri = new Uri( - ASPNETIdentityConfig.OAuthAuthorizationServerEndpointsRootURI - + ASPNETIdentityConfig.OAuthIntrospectTokenWebAPI); + ASPNETIdentityConfig.OAuth2AuthorizationServerEndpointsRootURI + + ASPNETIdentityConfig.OAuth2IntrospectTokenWebAPI); // Introspectエンドポイントにアクセス @@ -2405,7 +2485,7 @@ public async Task OAuthAuthorizationCodeGrantClient2(OAuthAuthoriz // 画面の表示。 ModelState.Clear(); - return View("OAuthAuthorizationCodeGrantClient", model); + return View("OAuth2AuthorizationCodeGrantClient", model); } else { @@ -2432,7 +2512,7 @@ public async Task OAuthAuthorizationCodeGrantClient2(OAuthAuthoriz /// [HttpGet] [AllowAnonymous] - public ActionResult OAuthImplicitGrantClient() + public ActionResult OAuth2ImplicitGrantClient() { if (!ASPNETIdentityConfig.IsLockedDownRedirectEndpoint) { diff --git a/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Controllers/HomeController.cs b/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Controllers/HomeController.cs index 0bd0b82e..e5581e58 100644 --- a/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Controllers/HomeController.cs +++ b/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Controllers/HomeController.cs @@ -100,12 +100,23 @@ private string AssembleOidcStarter(string response_type) + "&nonce=" + this.Nonce; } + /// FAPI1スターターを組み立てて返す + /// string + /// 組み立てたFAPI1スターター + private string AssembleFAPI1Starter(string response_type) + { + return this.OAuthAuthorizeEndpoint + + string.Format( + "?client_id={0}&response_type={1}&scope={2}&state={3}", + this.ClientId, response_type, ASPNETIdentityConst.StandardScopes, "fapi1:" + this.State); + } + /// 初期化 private void Init() { this.OAuthAuthorizeEndpoint = - ASPNETIdentityConfig.OAuthAuthorizationServerEndpointsRootURI - + ASPNETIdentityConfig.OAuthAuthorizeEndpoint; + ASPNETIdentityConfig.OAuth2AuthorizationServerEndpointsRootURI + + ASPNETIdentityConfig.OAuth2AuthorizeEndpoint; this.ClientId = OAuth2Helper.GetInstance().GetClientIdByName("TestClient"); this.State = GetPassword.Generate(10, 0); // 記号は入れない。 @@ -118,10 +129,11 @@ private void Init() /// 保存 private void Save() { - // テスト用にstate, code_verifierを、Session, Cookieに保存 + // テスト用にstate, nonce, code_verifierを、Session, Cookieに保存 // ・Session : サイト分割時 // ・Cookie : 同一サイト時 + // state Session["test_state"] = this.State; if (Request.Cookies["test_state"] == null) { @@ -135,6 +147,21 @@ private void Save() } } + // nonce + Session["test_nonce"] = this.Nonce; + if (Request.Cookies["test_nonce"] == null) + { + Response.Cookies["test_nonce"].Value = this.Nonce; + } + else + { + if (string.IsNullOrEmpty(Request.Cookies["test_nonce"].Value)) + { + Response.Cookies["test_nonce"].Value = this.Nonce; + } + } + + // code_verifier Session["test_code_verifier"] = this.CodeVerifier; if (Request.Cookies["test_code_verifier"] == null) { @@ -156,7 +183,7 @@ private void Save() /// OAuthStarters /// ActionResult [HttpGet] - public ActionResult OAuthStarters() + public ActionResult OAuth2Starters() { return View(); } @@ -175,7 +202,7 @@ public ActionResult AuthorizationCode() // Authorization Code Flow return Redirect(this.AssembleOAuth2Starter( - ASPNETIdentityConst.AuthorizationCodeResponseType)); + OAuth2AndOIDCConst.AuthorizationCodeResponseType)); } /// Test Authorization Code Flow (form_post) @@ -188,7 +215,7 @@ public ActionResult AuthorizationCode_FormPost() // Authorization Code Flow (form_post) return Redirect(this.AssembleOAuth2Starter( - ASPNETIdentityConst.AuthorizationCodeResponseType) + OAuth2AndOIDCConst.AuthorizationCodeResponseType) + "&response_mode=form_post"); } @@ -206,7 +233,7 @@ public ActionResult AuthorizationCode_OIDC() // Authorization Code Flow (OIDC) return Redirect(this.AssembleOidcStarter( - ASPNETIdentityConst.AuthorizationCodeResponseType) + OAuth2AndOIDCConst.AuthorizationCodeResponseType) + "&prompt=none"); } @@ -220,14 +247,14 @@ public ActionResult AuthorizationCode_OIDC_FormPost() // Authorization Code Flow (OIDC, form_post) return Redirect(this.AssembleOidcStarter( - ASPNETIdentityConst.AuthorizationCodeResponseType) + OAuth2AndOIDCConst.AuthorizationCodeResponseType) + "&prompt=none" + "&response_mode=form_post"); } #endregion - #region PKCE + #region PKCE(FAPI1) /// Test Authorization Code Flow (PKCE plain) /// ActionResult @@ -241,9 +268,9 @@ public ActionResult AuthorizationCode_PKCE_Plain() // Authorization Code Flow (PKCE plain) return Redirect(this.AssembleOAuth2Starter( - ASPNETIdentityConst.AuthorizationCodeResponseType) + OAuth2AndOIDCConst.AuthorizationCodeResponseType) + "&code_challenge=" + this.CodeChallenge - + "&code_challenge_method=plain"); + + "&code_challenge_method=" + OAuth2AndOIDCConst.PKCE_plain); } /// Test Authorization Code Flow (PKCE S256) @@ -253,14 +280,31 @@ public ActionResult AuthorizationCode_PKCE_S256() { this.Init(); this.CodeVerifier = GetPassword.Base64UrlSecret(50); - this.CodeChallenge = OAuth2Helper.PKCE_S256_CodeChallengeMethod(this.CodeVerifier); + this.CodeChallenge = OAuth2AndOIDCClient.PKCE_S256_CodeChallengeMethod(this.CodeVerifier); this.Save(); // Authorization Code Flow (PKCE S256) return Redirect(this.AssembleOAuth2Starter( - ASPNETIdentityConst.AuthorizationCodeResponseType) + OAuth2AndOIDCConst.AuthorizationCodeResponseType) + "&code_challenge=" + this.CodeChallenge - + "&code_challenge_method=S256"); + + "&code_challenge_method=" + OAuth2AndOIDCConst.PKCE_S256); + } + + #endregion + + #region FAPI1 + + /// Test Authorization Code Flow (FAPI1) + /// ActionResult + [HttpGet] + public ActionResult FAPI1AuthorizationCode() + { + this.Init(); + this.Save(); + + // Authorization Code Flow + return Redirect(this.AssembleFAPI1Starter( + OAuth2AndOIDCConst.AuthorizationCodeResponseType)); } #endregion @@ -281,7 +325,7 @@ public ActionResult Implicit() // Implicit Flow return Redirect(this.AssembleOAuth2Starter( - ASPNETIdentityConst.ImplicitResponseType)); + OAuth2AndOIDCConst.ImplicitResponseType)); } #endregion @@ -298,7 +342,7 @@ public ActionResult Implicit_OIDC1() // Implicit Flow 'id_token'(OIDC) return Redirect(this.AssembleOidcStarter( - ASPNETIdentityConst.OidcImplicit1_ResponseType)); + OAuth2AndOIDCConst.OidcImplicit1_ResponseType)); } @@ -312,7 +356,7 @@ public ActionResult Implicit_OIDC2() // Implicit Flow 'id_token token'(OIDC) return Redirect(this.AssembleOidcStarter( - ASPNETIdentityConst.OidcImplicit2_ResponseType)); + OAuth2AndOIDCConst.OidcImplicit2_ResponseType)); } #endregion @@ -333,7 +377,7 @@ public ActionResult Hybrid_OIDC1() // Hybrid Flow 'code id_token'(OIDC) return Redirect(this.AssembleOidcStarter( - ASPNETIdentityConst.OidcHybrid2_IdToken_ResponseType)); + OAuth2AndOIDCConst.OidcHybrid2_IdToken_ResponseType)); } /// Test Hybrid Flow 'code token'(OIDC) @@ -346,7 +390,7 @@ public ActionResult Hybrid_OIDC2() // Hybrid Flow 'code token'(OIDC) return Redirect(this.AssembleOidcStarter( - ASPNETIdentityConst.OidcHybrid2_Token_ResponseType)); + OAuth2AndOIDCConst.OidcHybrid2_Token_ResponseType)); } /// Test Hybrid Flow 'code id_token token'(OIDC) @@ -359,11 +403,15 @@ public ActionResult Hybrid_OIDC3() // Hybrid Flow 'code id_token token'(OIDC) return Redirect(this.AssembleOidcStarter( - ASPNETIdentityConst.OidcHybrid3_ResponseType)); + OAuth2AndOIDCConst.OidcHybrid3_ResponseType)); } #endregion + #region FAPI2 + + #endregion + #endregion #region Client Authentication Flow @@ -376,8 +424,8 @@ public ActionResult Hybrid_OIDC3() public async Task TestClientCredentialsFlow() { // Tokenエンドポイントにアクセス - string aud = ASPNETIdentityConfig.OAuthAuthorizationServerEndpointsRootURI - + ASPNETIdentityConfig.OAuthBearerTokenEndpoint; + string aud = ASPNETIdentityConfig.OAuth2AuthorizationServerEndpointsRootURI + + ASPNETIdentityConfig.OAuth2BearerTokenEndpoint; // ClientNameから、client_id, client_secretを取得。 string client_id = ""; @@ -397,15 +445,15 @@ public async Task TestClientCredentialsFlow() } string response = await OAuth2Helper.GetInstance() - .ClientCredentialsFlowAsync(new Uri( - ASPNETIdentityConfig.OAuthAuthorizationServerEndpointsRootURI - + ASPNETIdentityConfig.OAuthBearerTokenEndpoint), + .ClientCredentialsGrantAsync(new Uri( + ASPNETIdentityConfig.OAuth2AuthorizationServerEndpointsRootURI + + ASPNETIdentityConfig.OAuth2BearerTokenEndpoint), client_id, client_secret, ASPNETIdentityConst.StandardScopes); ViewBag.Response = response; - ViewBag.AccessToken = ((JObject)JsonConvert.DeserializeObject(response))["access_token"]; + ViewBag.AccessToken = ((JObject)JsonConvert.DeserializeObject(response))[OAuth2AndOIDCConst.AccessToken]; - return View("OAuthClientAuthenticationFlow"); + return View("OAuth2ClientAuthenticationFlow"); } #endregion @@ -418,8 +466,8 @@ public async Task TestClientCredentialsFlow() public async Task TestJWTBearerTokenFlow() { // Token2エンドポイントにアクセス - string aud = ASPNETIdentityConfig.OAuthAuthorizationServerEndpointsRootURI - + ASPNETIdentityConfig.OAuthBearerTokenEndpoint2; + string aud = ASPNETIdentityConfig.OAuth2AuthorizationServerEndpointsRootURI + + ASPNETIdentityConfig.OAuth2BearerTokenEndpoint2; // ClientNameから、client_id(iss)を取得。 string iss = ""; @@ -436,20 +484,20 @@ public async Task TestJWTBearerTokenFlow() } // テストなので秘密鍵は共通とする。 - string privateKey = GetConfigParameter.GetConfigValue("OAuth2JwtAssertionPrivatekey"); + string privateKey = OAuth2AndOIDCParams.OAuth2JwtAssertionPrivatekey; privateKey = CustomEncode.ByteToString(CustomEncode.FromBase64String(privateKey), CustomEncode.us_ascii); string response = await OAuth2Helper.GetInstance() .JwtBearerTokenFlowAsync(new Uri( - ASPNETIdentityConfig.OAuthAuthorizationServerEndpointsRootURI - + ASPNETIdentityConfig.OAuthBearerTokenEndpoint2), + ASPNETIdentityConfig.OAuth2AuthorizationServerEndpointsRootURI + + ASPNETIdentityConfig.OAuth2BearerTokenEndpoint2), JwtAssertion.CreateJwtBearerTokenFlowAssertion( iss, aud, new TimeSpan(0, 0, 30), ASPNETIdentityConst.StandardScopes, privateKey)); ViewBag.Response = response; - ViewBag.AccessToken = ((JObject)JsonConvert.DeserializeObject(response))["access_token"]; + ViewBag.AccessToken = ((JObject)JsonConvert.DeserializeObject(response))[OAuth2AndOIDCConst.AccessToken]; - return View("OAuthClientAuthenticationFlow"); + return View("OAuth2ClientAuthenticationFlow"); } #endregion diff --git a/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Controllers/ManageController.cs b/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Controllers/ManageController.cs index 891ac238..14499af4 100644 --- a/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Controllers/ManageController.cs +++ b/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Controllers/ManageController.cs @@ -30,13 +30,16 @@ using MultiPurposeAuthSite.Models.ASPNETIdentity.Util; using System; -using System.Collections.Generic; +using System.IO; +using System.Text; using System.Linq; +using System.Collections.Generic; +using System.Threading.Tasks; +using System.Security.Claims; + using System.Web; using System.Web.Mvc; using System.Net.Http; -using System.Threading.Tasks; -using System.Security.Claims; using Microsoft.Owin.Security; using Microsoft.AspNet.Identity; @@ -46,6 +49,7 @@ using Newtonsoft.Json.Linq; using Touryo.Infrastructure.Business.Presentation; +using Touryo.Infrastructure.Framework.Authentication; using Touryo.Infrastructure.Public.Str; using Touryo.Infrastructure.Public.Security; @@ -1464,7 +1468,7 @@ public async Task ExternalLoginCallback(string returnUrl) ASPNETIdentityConfig.TwitterAuthenticationClientId, ASPNETIdentityConfig.TwitterAuthenticationClientSecret); - email = (string)myInfo["email"]; // Microsoft.Owin.Security.Twitterでは、emailClaimとして取得できない。 + email = (string)myInfo[OAuth2AndOIDCConst.Scope_Email]; // Microsoft.Owin.Security.Twitterでは、emailClaimとして取得できない。 emailClaim = new Claim(ClaimTypes.Email, email); // emailClaimとして生成 } } @@ -1735,8 +1739,8 @@ public async Task ChargeByPaymentInformation() { // 課金のテスト処理 string ret = (string)JsonConvert.DeserializeObject( - await OAuth2Helper.GetInstance().CallOAuthChageToUserWebAPIAsync( - (string)Session["access_token"], "jpy", "1000")); + await OAuth2Helper.GetInstance().CallOAuth2ChageToUserWebAPIAsync( + (string)Session[OAuth2AndOIDCConst.AccessToken], "jpy", "1000")); if (ret == "OK") { @@ -2141,21 +2145,21 @@ public ActionResult GetOAuth2Token(ManageIndexViewModel model) if (ASPNETIdentityConfig.CanEditOAuth2Data && ASPNETIdentityConfig.EnableEditingOfUserAttribute) { - // OAuthAuthorizationCodeGrantClientViewModelの検証 + // OAuth2AuthorizationCodeGrantClientViewModelの検証 if (ModelState.IsValid) { // 認可エンドポイント string oAuthAuthorizeEndpoint = - ASPNETIdentityConfig.OAuthAuthorizationServerEndpointsRootURI - + ASPNETIdentityConfig.OAuthAuthorizeEndpoint; + ASPNETIdentityConfig.OAuth2AuthorizationServerEndpointsRootURI + + ASPNETIdentityConfig.OAuth2AuthorizeEndpoint; // client_id string client_id = OAuth2Helper.GetInstance().GetClientIdByName(User.Identity.Name); // redirect_uri string redirect_uri = CustomEncode.UrlEncode2( - ASPNETIdentityConfig.OAuthClientEndpointsRootURI - + ASPNETIdentityConfig.OAuthAuthorizationCodeGrantClient_Manage); + ASPNETIdentityConfig.OAuth2ClientEndpointsRootURI + + ASPNETIdentityConfig.OAuth2AuthorizationCodeGrantClient_Manage); // state (nonce) // 記号は入れない。 string state = GetPassword.Generate(10, 0); @@ -2356,6 +2360,141 @@ public async Task RemoveFIDO2Data() #endregion + #region GDPR + + /// + /// GDPR対策処理 + /// GET: /Manage/ManageGdprData + /// + /// ActionResultを非同期に返す + [HttpGet] + public ActionResult ManageGdprData() + { + if (ASPNETIdentityConfig.CanUseGdprFunction) + //&& ASPNETIdentityConfig.EnableEditingOfUserAttribute) + { + return View(); + } + else + { + // エラー画面 + return View("Error"); + } + } + + /// + /// GDPR対策のユーザデータ照会処理 + /// POST: /Manage/ReferGdprPersonalData + /// + /// ActionResultを非同期に返す + [HttpPost] + [ValidateAntiForgeryToken] + public async Task ReferGdprPersonalData() + { + if (ASPNETIdentityConfig.CanUseGdprFunction) + //&& ASPNETIdentityConfig.EnableEditingOfUserAttribute) + { + // ユーザの検索 + ApplicationUser user = await UserManager.FindByIdAsync(User.Identity.GetUserId()); + + using (MemoryStream ms = new MemoryStream()) + { + using (StreamWriter streamWriter = new StreamWriter(ms, Encoding.GetEncoding(CustomEncode.UTF_8))) + { + streamWriter.WriteLine(JsonConvert.SerializeObject(user)); + streamWriter.Flush(); + } + + return File(ms.ToArray(), "application/json", "user.json"); + } + } + else + { + // エラー画面 + return View("Error"); + } + } + + /// + /// GDPR対策のユーザデータ削除処理 + /// POST: /Manage/DeleteGdprPersonalData + /// + /// ActionResultを非同期に返す + [HttpPost] + [ValidateAntiForgeryToken] + public async Task DeleteGdprPersonalData() + { + if (ASPNETIdentityConfig.CanUseGdprFunction) + //&& ASPNETIdentityConfig.EnableEditingOfUserAttribute) + { + // ユーザの検索 + ApplicationUser user = await UserManager.FindByIdAsync(User.Identity.GetUserId()); + + #region データ消去 + // 既定の属性 + //user.Id = ""; + user.UserName = user.Id; + user.PasswordHash = ""; + user.Email = user.Id + "@yyy.com"; + user.EmailConfirmed = false; + user.PhoneNumber = user.Id; + user.PhoneNumberConfirmed = false; + user.AccessFailedCount = 0; + user.LockoutEnabled = false; + user.LockoutEndDateUtc = DateTime.MaxValue; + //user.SecurityStamp = user.SecurityStamp; + user.TwoFactorEnabled = false; + // Collection + //user.Roles = null; + //user.Logins = null; + //user.Claims = null; + + // 追加の属性 + user.ClientID = user.Id; + user.PaymentInformation = ""; + user.UnstructuredData = ""; + user.FIDO2PublicKey = ""; + //user.CreatedDate = ; + //user.PasswordChangeDate = + #endregion + + // ユーザ・データの削除 + IdentityResult result = null; + + foreach (UserLoginInfo l in user.Logins) + { + result = await UserManager.RemoveLoginAsync(user.Id, l); + } + user.Logins = null; + + foreach (Claim c in user.Claims) + { + result = await UserManager.RemoveClaimAsync(user.Id, c); + } + user.Claims = null; + + result = await UserManager.UpdateAsync(user); + + if (result.Succeeded) + { + // サインアウト(Cookieの削除) + AuthenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie); + //// オペレーション・トレース・ログ出力 + //Logging.MyOperationTrace(string.Format("{0}({1}) has signed out.", user.Id, user.UserName)); + + // リダイレクト "Index", "Home"へ + return RedirectToAction("Index", "Home"); + } + else { } + } + else { } + + // エラー画面 + return View("Error"); + } + + #endregion + #region Client (Redirectエンドポイント) #region Authorization Codeグラント種別 @@ -2371,19 +2510,20 @@ public async Task RemoveFIDO2Data() /// /// [HttpPost] - public async Task OAuthAuthorizationCodeGrantClient(string code, string state) + //[ValidateAntiForgeryToken] // response_mode=form_postで実装しているためハズす。 + public async Task OAuth2AuthorizationCodeGrantClient(string code, string state) { if (ASPNETIdentityConfig.CanEditOAuth2Data && ASPNETIdentityConfig.EnableEditingOfUserAttribute) { // Tokenエンドポイントにアクセス Uri tokenEndpointUri = new Uri( - ASPNETIdentityConfig.OAuthAuthorizationServerEndpointsRootURI - + ASPNETIdentityConfig.OAuthBearerTokenEndpoint); + ASPNETIdentityConfig.OAuth2AuthorizationServerEndpointsRootURI + + ASPNETIdentityConfig.OAuth2BearerTokenEndpoint); // 結果を格納する変数。 Dictionary dic = null; - OAuthAuthorizationCodeGrantClientViewModel model = new OAuthAuthorizationCodeGrantClientViewModel + OAuth2AuthorizationCodeGrantClientViewModel model = new OAuth2AuthorizationCodeGrantClientViewModel { Code = code }; @@ -2402,8 +2542,8 @@ public async Task OAuthAuthorizationCodeGrantClient(string code, s // 仲介コードからAccess Tokenを取得する。 string redirect_uri - = ASPNETIdentityConfig.OAuthClientEndpointsRootURI - + ASPNETIdentityConfig.OAuthAuthorizationCodeGrantClient_Manage; + = ASPNETIdentityConfig.OAuth2ClientEndpointsRootURI + + ASPNETIdentityConfig.OAuth2AuthorizationCodeGrantClient_Manage; // Tokenエンドポイントにアクセス model.Response = await OAuth2Helper.GetInstance() @@ -2415,14 +2555,14 @@ string redirect_uri // 余談:OpenID Connectであれば、ここで id_token 検証。 // 結果の表示 - model.AccessToken = dic["access_token"] ?? ""; + model.AccessToken = dic[OAuth2AndOIDCConst.AccessToken] ?? ""; model.AccessTokenJwtToJson = CustomEncode.ByteToString( CustomEncode.FromBase64UrlString(model.AccessToken.Split('.')[1]), CustomEncode.UTF_8); - model.RefreshToken = dic.ContainsKey("refresh_token") ? dic["refresh_token"] : ""; + model.RefreshToken = dic.ContainsKey(OAuth2AndOIDCConst.RefreshToken) ? dic[OAuth2AndOIDCConst.RefreshToken] : ""; // 課金処理で使用する。 - Session["access_token"] = model.AccessToken; + Session[OAuth2AndOIDCConst.AccessToken] = model.AccessToken; } else { @@ -2448,7 +2588,7 @@ string redirect_uri /// ActionResultを非同期に返す [HttpPost] [ValidateAntiForgeryToken] - public async Task OAuthAuthorizationCodeGrantClient2(OAuthAuthorizationCodeGrantClientViewModel model) + public async Task OAuth2AuthorizationCodeGrantClient2(OAuth2AuthorizationCodeGrantClientViewModel model) { if (ASPNETIdentityConfig.CanEditOAuth2Data && ASPNETIdentityConfig.EnableEditingOfUserAttribute) @@ -2462,8 +2602,8 @@ public async Task OAuthAuthorizationCodeGrantClient2(OAuthAuthoriz #region Tokenエンドポイントで、Refresh Tokenを使用してAccess Tokenを更新 Uri tokenEndpointUri = new Uri( - ASPNETIdentityConfig.OAuthAuthorizationServerEndpointsRootURI - + ASPNETIdentityConfig.OAuthBearerTokenEndpoint); + ASPNETIdentityConfig.OAuth2AuthorizationServerEndpointsRootURI + + ASPNETIdentityConfig.OAuth2BearerTokenEndpoint); // Tokenエンドポイントにアクセス @@ -2476,21 +2616,21 @@ public async Task OAuthAuthorizationCodeGrantClient2(OAuthAuthoriz dic = JsonConvert.DeserializeObject>(model.Response); // 結果の表示 - model.AccessToken = dic["access_token"] ?? ""; + model.AccessToken = dic[OAuth2AndOIDCConst.AccessToken] ?? ""; model.AccessTokenJwtToJson = CustomEncode.ByteToString( CustomEncode.FromBase64UrlString(model.AccessToken.Split('.')[1]), CustomEncode.UTF_8); - model.RefreshToken = dic["refresh_token"] ?? ""; + model.RefreshToken = dic[OAuth2AndOIDCConst.RefreshToken] ?? ""; // 課金処理で使用する。 - Session["access_token"] = model.AccessToken; + Session[OAuth2AndOIDCConst.AccessToken] = model.AccessToken; #endregion } // 画面の表示。 ModelState.Clear(); - return View("OAuthAuthorizationCodeGrantClient", model); + return View("OAuth2AuthorizationCodeGrantClient", model); } else { diff --git a/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Controllers/OAuthResourceApiController.cs b/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Controllers/OAuth2ResourceApiController.cs similarity index 63% rename from root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Controllers/OAuthResourceApiController.cs rename to root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Controllers/OAuth2ResourceApiController.cs index 4f053c90..ca5e7844 100644 --- a/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Controllers/OAuthResourceApiController.cs +++ b/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Controllers/OAuth2ResourceApiController.cs @@ -19,8 +19,8 @@ #endregion //********************************************************************************** -//* クラス名 :OAuthResourceApiController -//* クラス日本語名 :OAuthResourceServerのApiController +//* クラス名 :OAuth2ResourceApiController +//* クラス日本語名 :OAuth2ResourceServerのApiController //* //* 作成日時 :- //* 作成者 :- @@ -40,6 +40,7 @@ using MultiPurposeAuthSite.Models.ASPNETIdentity.OAuth2Extension; using System; +using System.Text; using System.Linq; using System.Collections.Generic; using System.Security.Claims; @@ -48,6 +49,7 @@ using System.Web; using System.Web.Http; using System.Web.Http.Cors; +using System.Net.Http; using System.Net.Http.Formatting; using Microsoft.Owin.Security; @@ -57,14 +59,17 @@ using Newtonsoft.Json; using Newtonsoft.Json.Linq; +using Newtonsoft.Json.Serialization; using Touryo.Infrastructure.Framework.Authentication; +using Touryo.Infrastructure.Framework.Presentation; +using Touryo.Infrastructure.Public.IO; using Touryo.Infrastructure.Public.Str; /// MultiPurposeAuthSite.Controllers namespace MultiPurposeAuthSite.Controllers { - /// OAuthResourceServerのApiController(ライブラリ) + /// OAuth2ResourceServerのApiController(ライブラリ) [EnableCors( // リソースへのアクセスを許可されている発生元 origins: "*", @@ -74,12 +79,12 @@ namespace MultiPurposeAuthSite.Controllers methods: "*", // SupportsCredentials = true)] - public class OAuthResourceApiController : ApiController + public class OAuth2ResourceApiController : ApiController { #region constructor /// constructor - public OAuthResourceApiController() + public OAuth2ResourceApiController() { } @@ -100,6 +105,224 @@ private ApplicationUserManager UserManager #region WebAPI + #region /.well-known/openid-configuration + + /// + /// OpenID Provider Configurationを返すWebAPI + /// GET: /jwks.json + /// + /// HttpResponseMessage + [HttpGet] + [Route(".well-known/openid-configuration")] + //[Authorize] + public HttpResponseMessage OpenIDConfig() + { + Dictionary OpenIDConfig = new Dictionary(); + + #region 基本 + + OpenIDConfig.Add("issuer", ASPNETIdentityConfig.OAuth2IssuerId); + OpenIDConfig.Add("access_token_issuer", ASPNETIdentityConfig.OAuth2IssuerId); + + OpenIDConfig.Add("authorization_endpoint", new List { + ASPNETIdentityConfig.OAuth2AuthorizationServerEndpointsRootURI + ASPNETIdentityConfig.OAuth2AuthorizeEndpoint, + ASPNETIdentityConfig.OAuth2AuthorizationServerEndpointsRootURI + ASPNETIdentityConfig.OAuth2AuthorizeEndpoint2 + }); + + OpenIDConfig.Add("token_endpoint", new List { + ASPNETIdentityConfig.OAuth2AuthorizationServerEndpointsRootURI + ASPNETIdentityConfig.OAuth2BearerTokenEndpoint, + ASPNETIdentityConfig.OAuth2AuthorizationServerEndpointsRootURI + ASPNETIdentityConfig.OAuth2BearerTokenEndpoint2 + }); + + OpenIDConfig.Add("userinfo_endpoint", + ASPNETIdentityConfig.OAuth2AuthorizationServerEndpointsRootURI + ASPNETIdentityConfig.OAuth2GetUserClaimsWebAPI); + + #endregion + + #region オプション + + List grant_types_supported = new List(); + List response_types_supported = new List(); + List scopes_supported = new List(); + + OpenIDConfig.Add("grant_types_supported", grant_types_supported); + OpenIDConfig.Add("response_types_supported", response_types_supported); + OpenIDConfig.Add("scopes_supported", scopes_supported); + + #region token + + scopes_supported = new List { + OAuth2AndOIDCConst.Scope_Auth, + OAuth2AndOIDCConst.Scope_Profile, + OAuth2AndOIDCConst.Scope_Email, + OAuth2AndOIDCConst.Scope_Phone, + OAuth2AndOIDCConst.Scope_Address, + OAuth2AndOIDCConst.Scope_UserID, + OAuth2AndOIDCConst.Scope_Roles + }; + + OpenIDConfig.Add("token_endpoint_auth_methods_supported", new List { + "client_secret_basic", + "private_key_jwt" + }); + + OpenIDConfig.Add("token_endpoint_auth_signing_alg_values_supported", new List { + "RS256" + }); + + #endregion + + #region grant_types and response_types + + grant_types_supported.Add(OAuth2AndOIDCConst.JwtBearerTokenFlowGrantType); + + if (ASPNETIdentityConfig.EnableAuthorizationCodeGrantType) + { + grant_types_supported.Add(OAuth2AndOIDCConst.AuthorizationCodeGrantType); + response_types_supported.Add(OAuth2AndOIDCConst.AuthorizationCodeResponseType); + } + else if (ASPNETIdentityConfig.EnableImplicitGrantType) + { + grant_types_supported.Add(OAuth2AndOIDCConst.ImplicitGrantType); + response_types_supported.Add(OAuth2AndOIDCConst.ImplicitResponseType); + } + else if (ASPNETIdentityConfig.EnableResourceOwnerPasswordCredentialsGrantType) + { + grant_types_supported.Add(OAuth2AndOIDCConst.ResourceOwnerPasswordCredentialsGrantType); + } + else if (ASPNETIdentityConfig.EnableClientCredentialsGrantType) + { + grant_types_supported.Add(OAuth2AndOIDCConst.ClientCredentialsGrantType); + } + else if (ASPNETIdentityConfig.EnableRefreshToken) + { + grant_types_supported.Add(OAuth2AndOIDCConst.RefreshTokenGrantType); + } + + #endregion + + #region OpenID Connect + + if (ASPNETIdentityConfig.EnableOpenIDConnect) + { + scopes_supported.Add(OAuth2AndOIDCConst.Scope_Openid); + + response_types_supported.Add(OAuth2AndOIDCConst.OidcImplicit2_ResponseType); + response_types_supported.Add(OAuth2AndOIDCConst.OidcHybrid2_Token_ResponseType); + response_types_supported.Add(OAuth2AndOIDCConst.OidcHybrid2_IdToken_ResponseType); + response_types_supported.Add(OAuth2AndOIDCConst.OidcHybrid3_ResponseType); + + // subject_types_supported + OpenIDConfig.Add("subject_types_supported", new List { + "pairwise" + }); + + // claims_supported + OpenIDConfig.Add("claims_supported", new List { + OAuth2AndOIDCConst.iss, + OAuth2AndOIDCConst.aud, + OAuth2AndOIDCConst.sub, + OAuth2AndOIDCConst.exp, + OAuth2AndOIDCConst.nbf, + OAuth2AndOIDCConst.iat, + OAuth2AndOIDCConst.jti, + OAuth2AndOIDCConst.nonce, + OAuth2AndOIDCConst.at_hash, + OAuth2AndOIDCConst.c_hash + }); + + OpenIDConfig.Add("id_token_signing_alg_values_supported", new List { + "RS256" + }); + + OpenIDConfig.Add("jwks_uri", "・・・"); + } + + #endregion + + #region OAuth2拡張 + + OpenIDConfig.Add("response_modes_supported", new List { + OAuth2AndOIDCConst.query, + OAuth2AndOIDCConst.form_post + }); + + #region revocation + + OpenIDConfig.Add("revocation_endpoint", new List { + ASPNETIdentityConfig.OAuth2AuthorizationServerEndpointsRootURI + ASPNETIdentityConfig.OAuth2RevokeTokenWebAPI + }); + + OpenIDConfig.Add("revocation_endpoint_auth_methods_supported", new List { + "client_secret_basic" + }); + + #endregion + + #region revocation + + OpenIDConfig.Add("introspection_endpoint", new List { + ASPNETIdentityConfig.OAuth2AuthorizationServerEndpointsRootURI + ASPNETIdentityConfig.OAuth2IntrospectTokenWebAPI + }); + + OpenIDConfig.Add("introspection_endpoint_auth_methods_supported", new List { + "none" + }); + + #endregion + + #region OAuth2拡張 + + OpenIDConfig.Add("code_challenge_methods_supported", new List { + OAuth2AndOIDCConst.PKCE_plain, + OAuth2AndOIDCConst.PKCE_S256 + }); + + #endregion + + OpenIDConfig.Add("service_documentation", "・・・"); + + #endregion + + #endregion + + // JsonSerializerSettingsを指定して、可読性の高いJSONを返す。 + return new HttpResponseMessage() + { + Content = new JsonContent(OpenIDConfig, + new JsonSerializerSettings + { + Formatting = Formatting.Indented, + ContractResolver = new CamelCasePropertyNamesContractResolver() + }) + }; + } + + #endregion + + #region /jwks.json + + /// + /// JWK Set documentを返すWebAPI + /// GET: /jwkcerts + /// + /// HttpResponseMessage + [HttpGet] + [Route("jwkcerts")] + //[Authorize] + public HttpResponseMessage JwksUri() + { + return new HttpResponseMessage() + { + Content = new JsonContent( + ResourceLoader.LoadAsString( + OAuth2AndOIDCParams.JwkSetFilePath, + Encoding.GetEncoding(CustomEncode.UTF_8))) + }; + } + + #endregion + #region /userinfo /// @@ -115,7 +338,7 @@ public async Task> GetUserClaims() // Claim情報を参照する。 // iss, aud, expのチェックは、AccessTokenFormatJwt.Unprotectで実施済。 ClaimsIdentity id = (ClaimsIdentity)User.Identity; - Claim claim_aud = id.FindFirst(ASPNETIdentityConst.Claim_Audience); + Claim claim_aud = id.FindFirst(OAuth2AndOIDCConst.Claim_Audience); // ユーザ認証を行なう。 ApplicationUser user = await UserManager.FindByIdAsync(User.Identity.GetUserId()); @@ -134,10 +357,10 @@ public async Task> GetUserClaims() } Dictionary userinfoClaimSet = new Dictionary(); - userinfoClaimSet.Add("sub", subject); + userinfoClaimSet.Add(OAuth2AndOIDCConst.sub, subject); // Scope - IEnumerable claimScope = id.FindAll(ASPNETIdentityConst.Claim_Scope).AsEnumerable(); + IEnumerable claimScope = id.FindAll(OAuth2AndOIDCConst.Claim_Scopes).AsEnumerable(); // scope値によって、返す値を変更する。 foreach (Claim scope in claimScope) @@ -149,18 +372,18 @@ public async Task> GetUserClaims() { #region OpenID Connect - case ASPNETIdentityConst.Scope_Profile: + case OAuth2AndOIDCConst.Scope_Profile: // ・・・ break; - case ASPNETIdentityConst.Scope_Email: - userinfoClaimSet.Add("email", user.Email); - userinfoClaimSet.Add("email_verified", user.EmailConfirmed.ToString()); + case OAuth2AndOIDCConst.Scope_Email: + userinfoClaimSet.Add(OAuth2AndOIDCConst.Scope_Email, user.Email); + userinfoClaimSet.Add(OAuth2AndOIDCConst.email_verified, user.EmailConfirmed.ToString()); break; - case ASPNETIdentityConst.Scope_Phone: - userinfoClaimSet.Add("phone_number", user.PhoneNumber); - userinfoClaimSet.Add("phone_number_verified", user.PhoneNumberConfirmed.ToString()); + case OAuth2AndOIDCConst.Scope_Phone: + userinfoClaimSet.Add(OAuth2AndOIDCConst.phone_number, user.PhoneNumber); + userinfoClaimSet.Add(OAuth2AndOIDCConst.phone_number_verified, user.PhoneNumberConfirmed.ToString()); break; - case ASPNETIdentityConst.Scope_Address: + case OAuth2AndOIDCConst.Scope_Address: // ・・・ break; @@ -168,12 +391,12 @@ public async Task> GetUserClaims() #region Else - case ASPNETIdentityConst.Scope_Userid: - userinfoClaimSet.Add(ASPNETIdentityConst.Scope_Userid, user.Id); + case OAuth2AndOIDCConst.Scope_UserID: + userinfoClaimSet.Add(OAuth2AndOIDCConst.Scope_UserID, user.Id); break; - case ASPNETIdentityConst.Scope_Roles: + case OAuth2AndOIDCConst.Scope_Roles: userinfoClaimSet.Add( - ASPNETIdentityConst.Scope_Roles, + OAuth2AndOIDCConst.Scope_Roles, await UserManager.GetRolesAsync(user.Id)); break; @@ -212,17 +435,17 @@ public Dictionary RevokeToken(FormDataCollection formData) // 変数 string[] temp = null; - string token = formData["token"]; - string token_type_hint = formData["token_type_hint"]; + string token = formData[OAuth2AndOIDCConst.token]; + string token_type_hint = formData[OAuth2AndOIDCConst.token_type_hint]; // クライアント認証 // クライアント識別子 - string authHeader = HttpContext.Current.Request.Headers["Authorization"]; + string authHeader = HttpContext.Current.Request.Headers[OAuth2AndOIDCConst.HttpHeader_Authorization]; temp = authHeader.Split(' '); - if (temp[0].ToLower() == "basic") + if (temp[0] == OAuth2AndOIDCConst.Basic) { temp = CustomEncode.ByteToString( CustomEncode.FromBase64String(temp[1]), CustomEncode.us_ascii).Split(':'); @@ -237,7 +460,7 @@ public Dictionary RevokeToken(FormDataCollection formData) { // 検証完了 - if (token_type_hint == "access_token") + if (token_type_hint == OAuth2AndOIDCConst.AccessToken) { // 検証 AccessTokenFormatJwt verifier = new AccessTokenFormatJwt(); @@ -256,14 +479,14 @@ public Dictionary RevokeToken(FormDataCollection formData) // jtiの取り出し Claim jti = ticket.Identity.Claims.Where( - x => x.Type == ASPNETIdentityConst.Claim_JwtId).FirstOrDefault(); + x => x.Type == OAuth2AndOIDCConst.Claim_JwtId).FirstOrDefault(); // access_token取消 OAuth2RevocationProvider.GetInstance().Create(jti.Value); return null; // 成功 } } - else if (token_type_hint == "refresh_token") + else if (token_type_hint == OAuth2AndOIDCConst.RefreshToken) { // refresh_token取消 if (RefreshTokenProvider.DeleteDirectly(token)) @@ -336,17 +559,17 @@ public Dictionary IntrospectToken(FormDataCollection formData) // 変数 string[] temp = null; - string token = formData["token"]; - string token_type_hint = formData["token_type_hint"]; + string token = formData[OAuth2AndOIDCConst.token]; + string token_type_hint = formData[OAuth2AndOIDCConst.token_type_hint]; // クライアント認証 // クライアント識別子 - string authHeader = HttpContext.Current.Request.Headers["Authorization"]; + string authHeader = HttpContext.Current.Request.Headers[OAuth2AndOIDCConst.HttpHeader_Authorization]; temp = authHeader.Split(' '); - if (temp[0].ToLower() == "basic") + if (temp[0] == OAuth2AndOIDCConst.Basic) { temp = CustomEncode.ByteToString( CustomEncode.FromBase64String(temp[1]), CustomEncode.us_ascii).Split(':'); @@ -362,7 +585,7 @@ public Dictionary IntrospectToken(FormDataCollection formData) // 検証完了 AuthenticationTicket ticket = null; - if (token_type_hint == "access_token") + if (token_type_hint == OAuth2AndOIDCConst.AccessToken) { // 検証 AccessTokenFormatJwt verifier = new AccessTokenFormatJwt(); @@ -380,31 +603,31 @@ public Dictionary IntrospectToken(FormDataCollection formData) // 検証成功 // メタデータの返却 ret.Add("active", "true"); - ret.Add("token_type", token_type_hint); + ret.Add(OAuth2AndOIDCConst.token_type, token_type_hint); string scopes = ""; foreach (Claim claim in ticket.Identity.Claims) { - if (claim.Type.StartsWith(ASPNETIdentityConst.Claim_Base)) + if (claim.Type.StartsWith(OAuth2AndOIDCConst.Claim_Base)) { - if (claim.Type == ASPNETIdentityConst.Claim_Scope) + if (claim.Type == OAuth2AndOIDCConst.Claim_Scopes) { scopes += claim.Value + " "; } else { ret.Add(claim.Type.Substring( - ASPNETIdentityConst.Claim_Base.Length), claim.Value); + OAuth2AndOIDCConst.Claim_Base.Length), claim.Value); } } } - ret.Add(ASPNETIdentityConst.Claim_Scope.Substring( - ASPNETIdentityConst.Claim_Base.Length), scopes.Trim()); + ret.Add(OAuth2AndOIDCConst.Claim_Scopes.Substring( + OAuth2AndOIDCConst.Claim_Base.Length), scopes.Trim()); return ret; // 成功 } } - else if (token_type_hint == "refresh_token") + else if (token_type_hint == OAuth2AndOIDCConst.RefreshToken) { // refresh_token参照 ticket = RefreshTokenProvider.ReferDirectly(token); @@ -421,26 +644,26 @@ public Dictionary IntrospectToken(FormDataCollection formData) // 検証成功 // メタデータの返却 ret.Add("active", "true"); - ret.Add("token_type", token_type_hint); + ret.Add(OAuth2AndOIDCConst.token_type, token_type_hint); string scopes = ""; foreach (Claim claim in ticket.Identity.Claims) { - if (claim.Type.StartsWith(ASPNETIdentityConst.Claim_Base)) + if (claim.Type.StartsWith(OAuth2AndOIDCConst.Claim_Base)) { - if (claim.Type == ASPNETIdentityConst.Claim_Scope) + if (claim.Type == OAuth2AndOIDCConst.Claim_Scopes) { scopes += claim.Value + " "; } else { ret.Add(claim.Type.Substring( - ASPNETIdentityConst.Claim_Base.Length), claim.Value); + OAuth2AndOIDCConst.Claim_Base.Length), claim.Value); } } } - ret.Add(ASPNETIdentityConst.Claim_Scope.Substring( - ASPNETIdentityConst.Claim_Base.Length), scopes.Trim()); + ret.Add(OAuth2AndOIDCConst.Claim_Scopes.Substring( + OAuth2AndOIDCConst.Claim_Base.Length), scopes.Trim()); return ret; // 成功 } @@ -478,11 +701,11 @@ public Dictionary IntrospectToken(FormDataCollection formData) #endregion - #region /OAuthBearerToken2 + #region /OAuth2BearerToken2 /// /// JWT bearer token authorizationグラント種別のTokenエンドポイント - /// POST: /OAuthBearerToken2 + /// POST: /OAuth2BearerToken2 /// /// /// grant_type = urn:ietf:params:oauth:grant-type:jwt-bearer @@ -490,9 +713,9 @@ public Dictionary IntrospectToken(FormDataCollection formData) /// /// Dictionary(string, string) [HttpPost] - [Route("OAuthBearerToken2")] + [Route("OAuth2BearerToken2")] //[Authorize] - public Dictionary OAuthBearerToken2(FormDataCollection formData) + public Dictionary OAuth2BearerToken2(FormDataCollection formData) { // 戻り値 // ・正常 @@ -501,17 +724,17 @@ public Dictionary OAuthBearerToken2(FormDataCollection formData) Dictionary err = new Dictionary(); // 変数 - string grant_type = formData["grant_type"]; - string assertion = formData["assertion"]; + string grant_type = formData[OAuth2AndOIDCConst.grant_type]; + string assertion = formData[OAuth2AndOIDCConst.assertion]; // クライアント認証 - if (grant_type == ASPNETIdentityConst.JwtBearerTokenFlowGrantType) + if (grant_type == OAuth2AndOIDCConst.JwtBearerTokenFlowGrantType) { Dictionary dic = JsonConvert.DeserializeObject>( CustomEncode.ByteToString(CustomEncode.FromBase64UrlString( assertion.Split('.')[1]), CustomEncode.us_ascii)); - string pubKey = OAuth2Helper.GetInstance().GetJwtAssertionPublickey(dic["iss"]); + string pubKey = OAuth2Helper.GetInstance().GetJwtAssertionPublickey(dic[OAuth2AndOIDCConst.iss]); pubKey = CustomEncode.ByteToString(CustomEncode.FromBase64String(pubKey), CustomEncode.us_ascii); if (!string.IsNullOrEmpty(pubKey)) @@ -524,8 +747,8 @@ public Dictionary OAuthBearerToken2(FormDataCollection formData) if (JwtAssertion.VerifyJwtBearerTokenFlowAssertion(assertion, out iss, out aud, out scopes, out jobj, pubKey)) { // aud 検証 - if (aud == ASPNETIdentityConfig.OAuthAuthorizationServerEndpointsRootURI - + ASPNETIdentityConfig.OAuthBearerTokenEndpoint2) + if (aud == ASPNETIdentityConfig.OAuth2AuthorizationServerEndpointsRootURI + + ASPNETIdentityConfig.OAuth2BearerTokenEndpoint2) { // ここからは、JwtAssertionではなく、JwtTokenを作るので、属性設定に注意。 ClaimsIdentity identity = OAuth2Helper.AddClaim( @@ -533,21 +756,21 @@ public Dictionary OAuthBearerToken2(FormDataCollection formData) AuthenticationProperties prop = new AuthenticationProperties(); prop.IssuedUtc = DateTimeOffset.UtcNow; - prop.ExpiresUtc = DateTimeOffset.Now.Add(ASPNETIdentityConfig.OAuthAccessTokenExpireTimeSpanFromMinutes); + prop.ExpiresUtc = DateTimeOffset.Now.Add(ASPNETIdentityConfig.OAuth2AccessTokenExpireTimeSpanFromMinutes); // token_type - ret.Add("token_type", "bearer"); + ret.Add(OAuth2AndOIDCConst.token_type, OAuth2AndOIDCConst.Bearer.ToLower()); // access_token AccessTokenFormatJwt verifier = new AccessTokenFormatJwt(); string access_token = verifier.Protect(new AuthenticationTicket(identity, prop)); - ret.Add("access_token", access_token); + ret.Add(OAuth2AndOIDCConst.AccessToken, access_token); // expires_in jobj = (JObject)JsonConvert.DeserializeObject( CustomEncode.ByteToString(CustomEncode.FromBase64UrlString( access_token.Split('.')[1]), CustomEncode.us_ascii)); - ret.Add("expires_in", (long.Parse((string)jobj["exp"]) - long.Parse((string)jobj["iat"])).ToString()); + ret.Add("expires_in", (long.Parse((string)jobj[OAuth2AndOIDCConst.exp]) - long.Parse((string)jobj[OAuth2AndOIDCConst.iat])).ToString()); // オペレーション・トレース・ログ出力 string clientName = OAuth2Helper.GetInstance().GetClientName(iss); @@ -606,12 +829,12 @@ public Dictionary OAuthBearerToken2(FormDataCollection formData) public async Task> TestHybridFlow(FormDataCollection formData) { // 変数 - string code = formData["code"]; + string code = formData[OAuth2AndOIDCConst.code]; // Tokenエンドポイントにアクセス Uri tokenEndpointUri = new Uri( - ASPNETIdentityConfig.OAuthAuthorizationServerEndpointsRootURI - + ASPNETIdentityConfig.OAuthBearerTokenEndpoint); + ASPNETIdentityConfig.OAuth2AuthorizationServerEndpointsRootURI + + ASPNETIdentityConfig.OAuth2BearerTokenEndpoint); // 結果を格納する変数。 Dictionary dic = null; @@ -622,8 +845,8 @@ public async Task> TestHybridFlow(FormDataCollection // Hybridは、Implicitのredirect_uriを使用 string redirect_uri - = ASPNETIdentityConfig.OAuthClientEndpointsRootURI - + ASPNETIdentityConfig.OAuthImplicitGrantClient_Account; + = ASPNETIdentityConfig.OAuth2ClientEndpointsRootURI + + ASPNETIdentityConfig.OAuth2ImplicitGrantClient_Account; // Tokenエンドポイントにアクセス string response = await OAuth2Helper.GetInstance() @@ -632,7 +855,7 @@ string redirect_uri // UserInfoエンドポイントにアクセス dic = JsonConvert.DeserializeObject>( - await OAuth2Helper.GetInstance().GetUserInfoAsync(dic["access_token"])); + await OAuth2Helper.GetInstance().GetUserInfoAsync(dic[OAuth2AndOIDCConst.AccessToken])); return dic; } diff --git a/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ASPNETIdentity/ASPNETIdentityConfig.cs b/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ASPNETIdentity/ASPNETIdentityConfig.cs index 0f483e27..2c4d183f 100644 --- a/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ASPNETIdentity/ASPNETIdentityConfig.cs +++ b/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ASPNETIdentity/ASPNETIdentityConfig.cs @@ -855,7 +855,7 @@ public static bool CanEditOAuth2Data get { return - ASPNETIdentityConfig.EquipOAuthServer + ASPNETIdentityConfig.EquipOAuth2Server && Convert.ToBoolean(ConfigurationManager.AppSettings["CanEditOAuth2Data"]); } } @@ -867,9 +867,18 @@ public static bool CanEditFIDO2Data { get { - return - ASPNETIdentityConfig.EquipOAuthServer - && Convert.ToBoolean(ConfigurationManager.AppSettings["CanEditFIDO2Data"]); + return Convert.ToBoolean(ConfigurationManager.AppSettings["CanEditFIDO2Data"]); + } + } + + /// + /// CanUseGdprFunction + /// + public static bool CanUseGdprFunction + { + get + { + return Convert.ToBoolean(ConfigurationManager.AppSettings["CanUseGdprFunction"]); } } @@ -906,64 +915,64 @@ public static bool CanEditPayment #endregion - #region OAuth Client & Server + #region OAuth2 Client & Server #region 共通設定 /// - /// OAuthServerを実装しているか・どうか + /// OAuth2Serverを実装しているか・どうか /// - public static bool EquipOAuthServer + public static bool EquipOAuth2Server { get { - return Convert.ToBoolean(ConfigurationManager.AppSettings["EquipOAuthServer"]); + return Convert.ToBoolean(ConfigurationManager.AppSettings["EquipOAuth2Server"]); } } - #region OAuth関連プロパティ + #region OAuth2関連プロパティ /// - /// OAuthのAllowInsecureHttpEndpointsプロパティ値 + /// OAuth2のAllowInsecureHttpEndpointsプロパティ値 /// - public static bool AllowOAuthInsecureHttpEndpoints + public static bool AllowOAuth2InsecureHttpEndpoints { get { - return Convert.ToBoolean(ConfigurationManager.AppSettings["AllowOAuthInsecureHttpEndpoints"]); + return Convert.ToBoolean(ConfigurationManager.AppSettings["AllowOAuth2InsecureHttpEndpoints"]); } } /// - /// OAuthのAuthorizeEndpointCanDisplayErrorsプロパティ値 + /// OAuth2のAuthorizeEndpointCanDisplayErrorsプロパティ値 /// - public static bool OAuthAuthorizeEndpointCanDisplayErrors + public static bool OAuth2AuthorizeEndpointCanDisplayErrors { get { - return Convert.ToBoolean(ConfigurationManager.AppSettings["OAuthAuthorizeEndpointCanDisplayErrors"]); + return Convert.ToBoolean(ConfigurationManager.AppSettings["OAuth2AuthorizeEndpointCanDisplayErrors"]); } } /// - /// OAuthのAccessTokenの有効期限 + /// OAuth2のAccessTokenの有効期限 /// - public static TimeSpan OAuthAccessTokenExpireTimeSpanFromMinutes + public static TimeSpan OAuth2AccessTokenExpireTimeSpanFromMinutes { get { - return TimeSpan.FromMinutes(int.Parse(ConfigurationManager.AppSettings["OAuthAccessTokenExpireTimeSpanFromMinutes"])); + return TimeSpan.FromMinutes(int.Parse(ConfigurationManager.AppSettings["OAuth2AccessTokenExpireTimeSpanFromMinutes"])); } } /// - /// OAuthのRefreshTokenの有効期限 + /// OAuth2のRefreshTokenの有効期限 /// - public static TimeSpan OAuthRefreshTokenExpireTimeSpanFromDays + public static TimeSpan OAuth2RefreshTokenExpireTimeSpanFromDays { get { - return TimeSpan.FromDays(int.Parse(ConfigurationManager.AppSettings["OAuthRefreshTokenExpireTimeSpanFromDays"])); + return TimeSpan.FromDays(int.Parse(ConfigurationManager.AppSettings["OAuth2RefreshTokenExpireTimeSpanFromDays"])); } } @@ -972,48 +981,37 @@ public static TimeSpan OAuthRefreshTokenExpireTimeSpanFromDays #region JWT関連プロパティ /// - /// JWTのIssuerId (OAuth Server) + /// JWTのIssuerId (OAuth2 Server) /// - public static string OAuthIssuerId + public static string OAuth2IssuerId { get { - return ConfigurationManager.AppSettings["OAuthIssuerId"]; + return ConfigurationManager.AppSettings["OAuth2IssuerId"]; } } #region 証明書 /// - /// OAuthのAccess Tokenに使用するJWTの署名用証明書(*.pfx)のパスワード - /// - public static string OAuthJWTPassword - { - get - { - return ConfigurationManager.AppSettings["OAuthJWTPassword"]; - } - } - - /// - /// OAuthのAccess Tokenに使用するJWTの署名用証明書(*.pfx)のパス + /// OAuth2/OIDCのTokenに使用するJWTの署名用証明書(*.pfx)のパスワード /// - public static string OAuthJWT_pfx + public static string OAuth2JWTPassword { get { - return ConfigurationManager.AppSettings["OAuthJWT_pfx"]; + return ConfigurationManager.AppSettings["OAuth2JWTPassword"]; } } /// - /// OAuthのAccess Tokenに使用するJWTの検証用証明書(*.cer)のパス + /// OAuth2/OIDCのTokenに使用するJWTの署名用証明書(*.pfx)のパス /// - public static string OAuthJWT_cer + public static string OAuth2JWT_pfx { get { - return ConfigurationManager.AppSettings["OAuthJWT_cer"]; + return ConfigurationManager.AppSettings["OAuth2JWT_pfx"]; } } @@ -1045,12 +1043,12 @@ public static bool EnableImplicitGrantType } } - /// EnableResourceOwnerCredentialsGrantType - public static bool EnableResourceOwnerCredentialsGrantType + /// EnableResourceOwnerPasswordCredentialsGrantType + public static bool EnableResourceOwnerPasswordCredentialsGrantType { get { - return Convert.ToBoolean(ConfigurationManager.AppSettings["EnableResourceOwnerCredentialsGrantType"]); + return Convert.ToBoolean(ConfigurationManager.AppSettings["EnableResourceOwnerPasswordCredentialsGrantType"]); } } @@ -1086,65 +1084,65 @@ public static bool EnableOpenIDConnect #region エンドポイント /// - /// OAuthのAuthorizationServerのEndpointのRootのURI + /// OAuth2のAuthorizationServerのEndpointのRootのURI /// - public static string OAuthAuthorizationServerEndpointsRootURI + public static string OAuth2AuthorizationServerEndpointsRootURI { get { - return ConfigurationManager.AppSettings["OAuthAuthorizationServerEndpointsRootURI"]; + return ConfigurationManager.AppSettings["OAuth2AuthorizationServerEndpointsRootURI"]; } } #region 既定 /// - /// OAuthのAuthorizeエンドポイント + /// OAuth2のAuthorizeエンドポイント /// - public static string OAuthAuthorizeEndpoint + public static string OAuth2AuthorizeEndpoint { get { - return ConfigurationManager.AppSettings["OAuthAuthorizeEndpoint"]; + return ConfigurationManager.AppSettings["OAuth2AuthorizeEndpoint"]; } } /// - /// OAuthのBearerTokenのTokenエンドポイント + /// OAuth2のBearerTokenのTokenエンドポイント /// - public static string OAuthBearerTokenEndpoint + public static string OAuth2BearerTokenEndpoint { get { - return ConfigurationManager.AppSettings["OAuthBearerTokenEndpoint"]; + return ConfigurationManager.AppSettings["OAuth2BearerTokenEndpoint"]; } } #endregion - #region OAuth拡張 + #region OAuth2拡張 #region Authorize&Token2 /// - /// Financial API用のOAuthのAuthorizeエンドポイント + /// Financial API用のOAuth2のAuthorizeエンドポイント /// - public static string OAuthAuthorizeEndpoint2 + public static string OAuth2AuthorizeEndpoint2 { get { - return ConfigurationManager.AppSettings["OAuthAuthorizeEndpoint2"]; + return ConfigurationManager.AppSettings["OAuth2AuthorizeEndpoint2"]; } } /// /// JWT bearer token flow用のTokenエンドポイント /// - public static string OAuthBearerTokenEndpoint2 + public static string OAuth2BearerTokenEndpoint2 { get { - return ConfigurationManager.AppSettings["OAuthBearerTokenEndpoint2"]; + return ConfigurationManager.AppSettings["OAuth2BearerTokenEndpoint2"]; } } @@ -1153,35 +1151,35 @@ public static string OAuthBearerTokenEndpoint2 #region WebAPI /// - /// OAuthで認可したユーザ情報のClaimを発行するWebAPI + /// OAuth2/OIDCで認可したユーザ情報のClaimを発行するWebAPI /// - public static string OAuthGetUserClaimsWebAPI + public static string OAuth2GetUserClaimsWebAPI { get { - return ConfigurationManager.AppSettings["OAuthGetUserClaimsWebAPI"]; + return ConfigurationManager.AppSettings["OAuth2GetUserClaimsWebAPI"]; } } /// - /// OAuthで認可したTokenを無効化するWebAPI + /// OAuth2で認可したTokenを無効化するWebAPI /// - public static string OAuthRevokeTokenWebAPI + public static string OAuth2RevokeTokenWebAPI { get { - return ConfigurationManager.AppSettings["OAuthRevokeTokenWebAPI"]; + return ConfigurationManager.AppSettings["OAuth2RevokeTokenWebAPI"]; } } /// - /// OAuthで認可したTokenのメタデータを返すWebAPI + /// OAuth2で認可したTokenのメタデータを返すWebAPI /// - public static string OAuthIntrospectTokenWebAPI + public static string OAuth2IntrospectTokenWebAPI { get { - return ConfigurationManager.AppSettings["OAuthIntrospectTokenWebAPI"]; + return ConfigurationManager.AppSettings["OAuth2IntrospectTokenWebAPI"]; } } @@ -1194,13 +1192,13 @@ public static string OAuthIntrospectTokenWebAPI #region Token取得用 /// - /// ManageController.OAuthAuthorizationCodeGrantClientのRedirectエンドポイント + /// ManageController.OAuth2AuthorizationCodeGrantClientのRedirectエンドポイント /// - public static string OAuthAuthorizationCodeGrantClient_Manage + public static string OAuth2AuthorizationCodeGrantClient_Manage { get { - return ConfigurationManager.AppSettings["OAuthAuthorizationCodeGrantClient_Manage"]; + return ConfigurationManager.AppSettings["OAuth2AuthorizationCodeGrantClient_Manage"]; } } @@ -1243,13 +1241,13 @@ public static string TestChageToUserWebAPI #region 静的設定 /// - /// OAuthのClientのInformation + /// OAuth2のClientのInformation /// - public static string OAuthClientsInformation + public static string OAuth2ClientsInformation { get { - return ConfigurationManager.AppSettings["OAuthClientsInformation"]; + return ConfigurationManager.AppSettings["OAuth2ClientsInformation"]; } } @@ -1258,37 +1256,37 @@ public static string OAuthClientsInformation #region エンドポイント /// - /// OAuthのClientのEndpointのRootURI + /// OAuth2のClientのEndpointのRootURI /// - public static string OAuthClientEndpointsRootURI + public static string OAuth2ClientEndpointsRootURI { get { - return ConfigurationManager.AppSettings["OAuthClientEndpointsRootURI"]; + return ConfigurationManager.AppSettings["OAuth2ClientEndpointsRootURI"]; } } #region Redirect /// - /// AccountController.OAuthAuthorizationCodeGrantClientのRedirectエンドポイント + /// AccountController.OAuth2AuthorizationCodeGrantClientのRedirectエンドポイント /// - public static string OAuthAuthorizationCodeGrantClient_Account + public static string OAuth2AuthorizationCodeGrantClient_Account { get { - return ConfigurationManager.AppSettings["OAuthAuthorizationCodeGrantClient_Account"]; + return ConfigurationManager.AppSettings["OAuth2AuthorizationCodeGrantClient_Account"]; } } /// - /// AccountController.OAuthImplicitGrantClientのRedirectエンドポイント + /// AccountController.OAuth2ImplicitGrantClientのRedirectエンドポイント /// - public static string OAuthImplicitGrantClient_Account + public static string OAuth2ImplicitGrantClient_Account { get { - return ConfigurationManager.AppSettings["OAuthImplicitGrantClient_Account"]; + return ConfigurationManager.AppSettings["OAuth2ImplicitGrantClient_Account"]; } } @@ -1301,7 +1299,7 @@ public static bool IsLockedDownRedirectEndpoint { return Convert.ToBoolean(ConfigurationManager.AppSettings["IsLockedDownRedirectEndpoint"]) - || !ASPNETIdentityConfig.EquipOAuthServer; // IsLockedDownがfalseでもOAuthServerがfalseならtrueを返す. + || !ASPNETIdentityConfig.EquipOAuth2Server; // IsLockedDownがfalseでもOAuthServerがfalseならtrueを返す. } } @@ -1316,13 +1314,13 @@ public static bool IsLockedDownRedirectEndpoint #region エンドポイント /// - /// OAuthのResourceServerのEndpointのRootURI + /// OAuth2のResourceServerのEndpointのRootURI /// - public static string OAuthResourceServerEndpointsRootURI + public static string OAuth2ResourceServerEndpointsRootURI { get { - return ConfigurationManager.AppSettings["OAuthResourceServerEndpointsRootURI"]; + return ConfigurationManager.AppSettings["OAuth2ResourceServerEndpointsRootURI"]; } } diff --git a/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ASPNETIdentity/ASPNETIdentityConst.cs b/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ASPNETIdentity/ASPNETIdentityConst.cs index 17ac90ca..1147ff1e 100644 --- a/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ASPNETIdentity/ASPNETIdentityConst.cs +++ b/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ASPNETIdentity/ASPNETIdentityConst.cs @@ -31,13 +31,15 @@ //* 2017/04/24 西野 大介 新規 //********************************************************************************** +using Touryo.Infrastructure.Framework.Authentication; + /// MultiPurposeAuthSite.Models.ASPNETIdentity namespace MultiPurposeAuthSite.Models.ASPNETIdentity { /// ASPNETIdentityConst public class ASPNETIdentityConst { - #region Max + #region MaxLength /// UriのMaxLength public const int MaxLengthOfUri = 512; @@ -55,9 +57,7 @@ public class ASPNETIdentityConst public const int MaxLengthOfPassword = 100; #endregion - - #region Idp - + #region Roles /// SystemAdministrator or Administratorのrole @@ -74,172 +74,36 @@ public class ASPNETIdentityConst #endregion - #endregion - - #region STS - - #region GrantType - - /// Authorization Codeグラント種別 - public const string AuthorizationCodeGrantType = "authorization_code"; - - /// Implicitグラント種別 - public const string ImplicitGrantType = "-"; // Implicitには無い。 - - /// Resource Owner Password Credentialsグラント種別 - public const string ResourceOwnerPasswordCredentialsGrantType = "password"; - - /// Client Credentialsグラント種別 - public const string ClientCredentialsGrantType = "client_credentials"; - - /// Refresh Tokenグラント種別 - public const string RefreshTokenGrantType = "refresh_token"; - - /// JWT bearer token authorizationグラント種別 - public const string JwtBearerTokenFlowGrantType = "urn:ietf:params:oauth:grant-type:jwt-bearer"; - - #endregion - - #region ResponseType - - /// Authorization Codeグラント種別 - public const string AuthorizationCodeResponseType = "code"; - - /// Implicitグラント種別 - public const string ImplicitResponseType = "token"; - - /// OIDC - Implicit - public const string OidcImplicit1_ResponseType = "id_token"; - - /// OIDC - Implicit2 - public const string OidcImplicit2_ResponseType = "id_token token"; - - /// OIDC - Hybrid(IdToken) - public const string OidcHybrid2_IdToken_ResponseType = "code id_token"; - - /// OIDC - Hybrid(Token) - public const string OidcHybrid2_Token_ResponseType = "code token"; - - /// OIDC - Hybrid(IdToken & Token) - public const string OidcHybrid3_ResponseType = "code id_token token"; - - #endregion - - #region Claimのurn - - /// ベース部分 - public static readonly string Claim_Base = "urn:oauth:"; - - #region 標準Claim - - /// issuerクレームのurn - public static readonly string Claim_Issuer = Claim_Base + "iss"; - - /// audienceクレームのurn - public static readonly string Claim_Audience = Claim_Base + "aud"; - - /// scopeクレームのurn - public static readonly string Claim_Scope = Claim_Base + "scope"; - - #endregion - - #region 拡張Claim - - #region JWT - - /// expクレームのurn - public static readonly string Claim_ExpirationTime = Claim_Base + "exp"; - - /// nbfクレームのurn - public static readonly string Claim_NotBefore = Claim_Base + "nbf"; - - /// iatクレームのurn - public static readonly string Claim_IssuedAt = Claim_Base + "iat"; - - /// jtiクレームのurn - public static readonly string Claim_JwtId = Claim_Base + "jti"; - - #region OIDC - - /// nonceクレームのurn - public static readonly string Claim_Nonce = Claim_Base + "nonce"; - - #endregion - - #endregion - - #endregion - - #endregion - #region Scope - - #region Scopes + + #region ScopeSet /// 標準的なscope public static readonly string StandardScopes = - Scope_Profile + " " - + Scope_Email + " " - + Scope_Phone + " " - + Scope_Address + " " - + Scope_Userid; - // authは他のscopeをフィルタするので。 + OAuth2AndOIDCConst.Scope_Profile + " " + + OAuth2AndOIDCConst.Scope_Email + " " + + OAuth2AndOIDCConst.Scope_Phone + " " + + OAuth2AndOIDCConst.Scope_Address + " " + + OAuth2AndOIDCConst.Scope_UserID; /// OIDCのscope public static readonly string OidcScopes = - Scope_Openid + " " - + Scope_Profile + " " - + Scope_Email + " " - + Scope_Phone + " " - + Scope_Address + " " - + Scope_Userid; - // authは他のscopeをフィルタするので。 - + OAuth2AndOIDCConst.Scope_Openid + " " + + OAuth2AndOIDCConst.Scope_Profile + " " + + OAuth2AndOIDCConst.Scope_Email + " " + + OAuth2AndOIDCConst.Scope_Phone + " " + + OAuth2AndOIDCConst.Scope_Address + " " + + OAuth2AndOIDCConst.Scope_UserID; + /// ID連携 scope public static readonly string IdFederationScopes = - Scope_Openid + " " - + Scope_Profile + " " - + Scope_Email + " " - + Scope_Phone + " " - + Scope_Address + " " - + Scope_Userid + " " - + Scope_Roles; - // authは他のscopeをフィルタするので。 - - #endregion - - #region id_token用のscope - - /// id_tokenを要求するscope - public const string Scope_Openid = "openid"; - - /// profileを要求するscope - public const string Scope_Profile = "profile"; - - /// emailを要求するscope - public const string Scope_Email = "email"; - - /// phoneを要求するscope - public const string Scope_Phone = "phone"; - - /// addressを要求するscope - public const string Scope_Address = "address"; - - #endregion - - #region カスタムのscope - - /// useridを要求するscope - public const string Scope_Userid = "userid"; - - /// 認証を要求するscope - /// OAuth2用のprompt=none(@OIDC)的な - public const string Scope_Auth = "auth"; - - /// rolesを要求するscope - public const string Scope_Roles = "roles"; - - #endregion + OAuth2AndOIDCConst.Scope_Openid + " " + + OAuth2AndOIDCConst.Scope_Profile + " " + + OAuth2AndOIDCConst.Scope_Email + " " + + OAuth2AndOIDCConst.Scope_Phone + " " + + OAuth2AndOIDCConst.Scope_Address + " " + + OAuth2AndOIDCConst.Scope_UserID + " " + + OAuth2AndOIDCConst.Scope_Roles; #endregion diff --git a/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ASPNETIdentity/Entity/ApplicationUser.cs b/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ASPNETIdentity/Entity/ApplicationUser.cs index 27d12277..fe3adf04 100644 --- a/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ASPNETIdentity/Entity/ApplicationUser.cs +++ b/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ASPNETIdentity/Entity/ApplicationUser.cs @@ -19,15 +19,13 @@ //********************************************************************************** using System; -using System.Web; using System.Collections.Generic; - using System.Security.Claims; using System.Threading.Tasks; + using Microsoft.AspNet.Identity; -using Microsoft.AspNet.Identity.Owin; -using MultiPurposeAuthSite.Models.ASPNETIdentity.Manager; +using Newtonsoft.Json; /// MultiPurposeAuthSite.Models namespace MultiPurposeAuthSite.Models.ASPNETIdentity.Entity @@ -186,11 +184,36 @@ public static ApplicationUser CreateByRegister(string userName) /// Gets or sets the user name ( = Email) . /// public string UserName { get; set; } - + + /// salted / hashed form of the user password + private string _passwordHash = ""; + /// /// Gets or sets the salted / hashed form of the user password. /// - public string PasswordHash { get; set; } + [JsonIgnore] + public string PasswordHash + { + get + { + return this._passwordHash; + } + set + { + // Support "90-day update policy" of PCI DSS + if (string.IsNullOrEmpty(this._passwordHash)) + { + // 新規や、DBからロード + } + else + { + // 更新時 + this.PasswordChangeDate = DateTime.Now; + } + + this._passwordHash = value; + } + } #endregion @@ -315,6 +338,11 @@ public static ApplicationUser CreateByRegister(string userName) /// public DateTime CreatedDate { get; set; } = DateTime.Now ; + /// + /// パスワード更新日 + /// + public DateTime PasswordChangeDate { get; set; } = DateTime.Now; + #endregion #endregion diff --git a/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ASPNETIdentity/Entity/UserStore.cs b/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ASPNETIdentity/Entity/UserStore.cs index ef46e442..ecb5560e 100644 --- a/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ASPNETIdentity/Entity/UserStore.cs +++ b/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ASPNETIdentity/Entity/UserStore.cs @@ -375,12 +375,12 @@ public Task CreateAsync(ApplicationUser user) " [Id], [UserName], [PasswordHash], " + " [Email], [EmailConfirmed], [PhoneNumber], [PhoneNumberConfirmed], " + " [LockoutEnabled], [AccessFailedCount], [LockoutEndDateUtc], [SecurityStamp], [TwoFactorEnabled], " + - " [ClientID], [PaymentInformation], [UnstructuredData], [FIDO2PublicKey], [CreatedDate])" + + " [ClientID], [PaymentInformation], [UnstructuredData], [FIDO2PublicKey], [CreatedDate], [PasswordChangeDate])" + " VALUES ( " + " @Id, @UserName, @PasswordHash, " + " @Email, @EmailConfirmed, @PhoneNumber, @PhoneNumberConfirmed, " + " @LockoutEnabled, @AccessFailedCount, @LockoutEndDateUtc, @SecurityStamp, @TwoFactorEnabled, " + - " @ClientID, @PaymentInformation, @UnstructuredData, @FIDO2PublicKey, @CreatedDate)", user); + " @ClientID, @PaymentInformation, @UnstructuredData, @FIDO2PublicKey, @CreatedDate, @PasswordChangeDate)", user); break; @@ -391,12 +391,12 @@ public Task CreateAsync(ApplicationUser user) " \"Id\", \"UserName\", \"PasswordHash\", " + " \"Email\", \"EmailConfirmed\", \"PhoneNumber\", \"PhoneNumberConfirmed\", " + " \"LockoutEnabled\", \"AccessFailedCount\", \"LockoutEndDateUtc\", \"SecurityStamp\", \"TwoFactorEnabled\", " + - " \"ClientID\", \"PaymentInformation\", \"UnstructuredData\", \"FIDO2PublicKey\", \"CreatedDate\")" + + " \"ClientID\", \"PaymentInformation\", \"UnstructuredData\", \"FIDO2PublicKey\", \"CreatedDate\", \"PasswordChangeDate\")" + " VALUES ( " + " :Id, :UserName, :PasswordHash, " + " :Email, :EmailConfirmed, :PhoneNumber, :PhoneNumberConfirmed, " + " :LockoutEnabled, :AccessFailedCount, :LockoutEndDateUtc, :SecurityStamp, :TwoFactorEnabled, " + - " :ClientID, :PaymentInformation, :UnstructuredData, :FIDO2PublicKey, :CreatedDate)", + " :ClientID, :PaymentInformation, :UnstructuredData, :FIDO2PublicKey, :CreatedDate, :PasswordChangeDate)", new // 拡張メソッドで対策できる。 { Id = user.Id, @@ -415,7 +415,8 @@ public Task CreateAsync(ApplicationUser user) PaymentInformation = user.PaymentInformation, UnstructuredData = user.UnstructuredData, FIDO2PublicKey = user.FIDO2PublicKey, - CreatedDate = user.CreatedDate + CreatedDate = user.CreatedDate, + PasswordChangeDate = user.PasswordChangeDate }); break; @@ -427,12 +428,12 @@ public Task CreateAsync(ApplicationUser user) " \"id\", \"username\", \"passwordhash\", " + " \"email\", \"emailconfirmed\", \"phonenumber\", \"phonenumberconfirmed\", " + " \"lockoutenabled\", \"accessfailedcount\", \"lockoutenddateutc\", \"securitystamp\", \"twofactorenabled\", " + - " \"clientid\", \"paymentinformation\", \"unstructureddata\", \"fido2publickey\", \"createddate\")" + + " \"clientid\", \"paymentinformation\", \"unstructureddata\", \"fido2publickey\", \"createddate\", \"passwordchangedate\")" + " VALUES ( " + " @Id, @UserName, @PasswordHash, " + " @Email, @EmailConfirmed, @PhoneNumber, @PhoneNumberConfirmed, " + " @LockoutEnabled, @AccessFailedCount, @LockoutEndDateUtc, @SecurityStamp, @TwoFactorEnabled, " + - " @ClientID, @PaymentInformation, @UnstructuredData, @FIDO2PublicKey, @CreatedDate)", user); + " @ClientID, @PaymentInformation, @UnstructuredData, @FIDO2PublicKey, @CreatedDate, @PasswordChangeDate)", user); break; } @@ -813,7 +814,7 @@ public IQueryable Users /// ユーザー情報を更新 /// ApplicationUser /// - public async Task UpdateAsync(ApplicationUser user) + public Task UpdateAsync(ApplicationUser user) { // 更新系の機能のため、 //OnlySts.STSOnly_M(); @@ -821,144 +822,151 @@ public async Task UpdateAsync(ApplicationUser user) { // 何も更新しない。 // IUserLockoutStore機能などで使用するため。 - return; + return Task.FromResult(0); } // Debug - Logging.MyDebugSQLTrace("★ : " + + Logging.MyDebugSQLTrace("★ : " + MethodBase.GetCurrentMethod().DeclaringType.FullName + "." + MethodBase.GetCurrentMethod().Name + UserStore.GetParametersString(MethodBase.GetCurrentMethod().GetParameters())); try { - // ユーザー情報を取得 - ApplicationUser tgtUser = await this.FindByIdAsync(user.Id); + // MemoryStore同一インスタンス問題。 + // SerializeできないMemberもあり、DeepCloneもできず。 + + //// ユーザー情報を取得 + //ApplicationUser tgtUser = await this.FindByIdAsync(user.Id); + + //// ユーザー情報を更新 + //if (tgtUser == null) + //{ + // // なにもしない(というか何もできない) + //} + //else + //{ // ユーザー情報を更新 - if (tgtUser == null) - { - // なにもしない(というか何もできない) - } - else + switch (ASPNETIdentityConfig.UserStoreType) { - // ユーザー情報を更新 - switch (ASPNETIdentityConfig.UserStoreType) - { - case EnumUserStoreType.Memory: + case EnumUserStoreType.Memory: - // 既定の属性 - tgtUser.Id = user.Id; - tgtUser.UserName = user.UserName; - tgtUser.PasswordHash = user.PasswordHash; - tgtUser.Email = user.Email; - tgtUser.EmailConfirmed = user.EmailConfirmed; - tgtUser.PhoneNumber = user.PhoneNumber; - tgtUser.PhoneNumberConfirmed = user.PhoneNumberConfirmed; - tgtUser.AccessFailedCount = user.AccessFailedCount; - tgtUser.LockoutEnabled = user.LockoutEnabled; - tgtUser.LockoutEndDateUtc = user.LockoutEndDateUtc; - tgtUser.SecurityStamp = user.SecurityStamp; - tgtUser.TwoFactorEnabled = user.TwoFactorEnabled; - // Collection - tgtUser.Roles = user.Roles; - tgtUser.Logins = user.Logins; - tgtUser.Claims = user.Claims; - - // 追加の属性 - tgtUser.ClientID = user.ClientID; - tgtUser.PaymentInformation = user.PaymentInformation; - tgtUser.UnstructuredData = user.UnstructuredData; - tgtUser.FIDO2PublicKey = user.FIDO2PublicKey; + // MemoryStore同一インスタンス + + //// 既定の属性 + //tgtUser.Id = user.Id; + //tgtUser.UserName = user.UserName; + //tgtUser.PasswordHash = user.PasswordHash; + //tgtUser.Email = user.Email; + //tgtUser.EmailConfirmed = user.EmailConfirmed; + //tgtUser.PhoneNumber = user.PhoneNumber; + //tgtUser.PhoneNumberConfirmed = user.PhoneNumberConfirmed; + //tgtUser.AccessFailedCount = user.AccessFailedCount; + //tgtUser.LockoutEnabled = user.LockoutEnabled; + //tgtUser.LockoutEndDateUtc = user.LockoutEndDateUtc; + //tgtUser.SecurityStamp = user.SecurityStamp; + //tgtUser.TwoFactorEnabled = user.TwoFactorEnabled; + //// Collection + //tgtUser.Roles = user.Roles; + //tgtUser.Logins = user.Logins; + //tgtUser.Claims = user.Claims; + + //// 追加の属性 + //tgtUser.ClientID = user.ClientID; + //tgtUser.PaymentInformation = user.PaymentInformation; + //tgtUser.UnstructuredData = user.UnstructuredData; + //tgtUser.FIDO2PublicKey = user.FIDO2PublicKey; - break; + break; - case EnumUserStoreType.SqlServer: - case EnumUserStoreType.ODPManagedDriver: - case EnumUserStoreType.PostgreSQL: // DMBMS Provider + case EnumUserStoreType.SqlServer: + case EnumUserStoreType.ODPManagedDriver: + case EnumUserStoreType.PostgreSQL: // DMBMS Provider - using (IDbConnection cnn = DataAccess.CreateConnection()) - { - cnn.Open(); + using (IDbConnection cnn = DataAccess.CreateConnection()) + { + cnn.Open(); - // ユーザー情報を更新 - switch (ASPNETIdentityConfig.UserStoreType) - { - case EnumUserStoreType.SqlServer: + // ユーザー情報を更新 + switch (ASPNETIdentityConfig.UserStoreType) + { + case EnumUserStoreType.SqlServer: - cnn.Execute( - "UPDATE [Users] " + - "SET [UserName] = @UserName, [PasswordHash] = @PasswordHash, " + - " [Email] = @Email, [EmailConfirmed] = @EmailConfirmed, [PhoneNumber] = @PhoneNumber, [PhoneNumberConfirmed] = @PhoneNumberConfirmed, " + - " [LockoutEnabled] = @LockoutEnabled, [AccessFailedCount] = @AccessFailedCount, [LockoutEndDateUtc] = @LockoutEndDateUtc, [SecurityStamp] = @SecurityStamp, [TwoFactorEnabled] = @TwoFactorEnabled, " + - " [ClientID] = @ClientID, [PaymentInformation] = @PaymentInformation, [UnstructuredData] = @UnstructuredData, [FIDO2PublicKey] = @FIDO2PublicKey " + - "WHERE [Id] = @Id", user); + cnn.Execute( + "UPDATE [Users] " + + "SET [UserName] = @UserName, [PasswordHash] = @PasswordHash, " + + " [Email] = @Email, [EmailConfirmed] = @EmailConfirmed, [PhoneNumber] = @PhoneNumber, [PhoneNumberConfirmed] = @PhoneNumberConfirmed, " + + " [LockoutEnabled] = @LockoutEnabled, [AccessFailedCount] = @AccessFailedCount, [LockoutEndDateUtc] = @LockoutEndDateUtc, [SecurityStamp] = @SecurityStamp, [TwoFactorEnabled] = @TwoFactorEnabled, " + + " [ClientID] = @ClientID, [PaymentInformation] = @PaymentInformation, [UnstructuredData] = @UnstructuredData, [FIDO2PublicKey] = @FIDO2PublicKey, [PasswordChangeDate] = @PasswordChangeDate " + + "WHERE [Id] = @Id", user); - break; + break; - case EnumUserStoreType.ODPManagedDriver: + case EnumUserStoreType.ODPManagedDriver: - cnn.Execute( - "UPDATE \"Users\" " + - "SET \"UserName\" = :UserName, \"PasswordHash\" = :PasswordHash, " + - " \"Email\" = :Email, \"EmailConfirmed\" = :EmailConfirmed, \"PhoneNumber\" = :PhoneNumber, \"PhoneNumberConfirmed\" = :PhoneNumberConfirmed, " + - " \"LockoutEnabled\" = :LockoutEnabled, \"AccessFailedCount\" = :AccessFailedCount, \"LockoutEndDateUtc\" = :LockoutEndDateUtc, \"SecurityStamp\" = :SecurityStamp, \"TwoFactorEnabled\" = :TwoFactorEnabled, " + - " \"ClientID\" = :ClientID, \"PaymentInformation\" = :PaymentInformation, \"UnstructuredData\" = :UnstructuredData, \"FIDO2PublicKey\" = :FIDO2PublicKey " + - "WHERE \"Id\" = :Id", - new // 拡張メソッドで対策できる。 + cnn.Execute( + "UPDATE \"Users\" " + + "SET \"UserName\" = :UserName, \"PasswordHash\" = :PasswordHash, " + + " \"Email\" = :Email, \"EmailConfirmed\" = :EmailConfirmed, \"PhoneNumber\" = :PhoneNumber, \"PhoneNumberConfirmed\" = :PhoneNumberConfirmed, " + + " \"LockoutEnabled\" = :LockoutEnabled, \"AccessFailedCount\" = :AccessFailedCount, \"LockoutEndDateUtc\" = :LockoutEndDateUtc, \"SecurityStamp\" = :SecurityStamp, \"TwoFactorEnabled\" = :TwoFactorEnabled, " + + " \"ClientID\" = :ClientID, \"PaymentInformation\" = :PaymentInformation, \"UnstructuredData\" = :UnstructuredData, \"FIDO2PublicKey\" = :FIDO2PublicKey, \"PasswordChangeDate\" = :PasswordChangeDate " + + "WHERE \"Id\" = :Id", + new // 拡張メソッドで対策できる。 { - Id = user.Id, - UserName = user.UserName, - PasswordHash = user.PasswordHash, - Email = user.Email, - EmailConfirmed = user.EmailConfirmed ? -1 : 0, - PhoneNumber = user.PhoneNumber, - PhoneNumberConfirmed = user.PhoneNumberConfirmed ? -1 : 0, - LockoutEnabled = user.LockoutEnabled ? -1 : 0, - AccessFailedCount = user.AccessFailedCount, - LockoutEndDateUtc = user.LockoutEndDateUtc, - SecurityStamp = user.SecurityStamp, - TwoFactorEnabled = user.TwoFactorEnabled ? -1 : 0, - ClientID = user.ClientID, - PaymentInformation = user.PaymentInformation, - UnstructuredData = user.UnstructuredData, - FIDO2PublicKey = user.FIDO2PublicKey - }); - - break; + Id = user.Id, + UserName = user.UserName, + PasswordHash = user.PasswordHash, + Email = user.Email, + EmailConfirmed = user.EmailConfirmed ? -1 : 0, + PhoneNumber = user.PhoneNumber, + PhoneNumberConfirmed = user.PhoneNumberConfirmed ? -1 : 0, + LockoutEnabled = user.LockoutEnabled ? -1 : 0, + AccessFailedCount = user.AccessFailedCount, + LockoutEndDateUtc = user.LockoutEndDateUtc, + SecurityStamp = user.SecurityStamp, + TwoFactorEnabled = user.TwoFactorEnabled ? -1 : 0, + ClientID = user.ClientID, + PaymentInformation = user.PaymentInformation, + UnstructuredData = user.UnstructuredData, + FIDO2PublicKey = user.FIDO2PublicKey, + PasswordChangeDate = user.PasswordChangeDate + }); - case EnumUserStoreType.PostgreSQL: + break; - cnn.Execute( - "UPDATE \"users\" " + - "SET \"username\" = @UserName, \"passwordhash\" = @PasswordHash, " + - " \"email\" = @Email, \"emailconfirmed\" = @EmailConfirmed, \"phonenumber\" = @PhoneNumber, \"phonenumberconfirmed\" = @PhoneNumberConfirmed, " + - " \"lockoutenabled\" = @LockoutEnabled, \"accessfailedcount\" = @AccessFailedCount, \"lockoutenddateutc\" = @LockoutEndDateUtc, \"securitystamp\" = @SecurityStamp, \"twofactorenabled\" = @TwoFactorEnabled, " + - " \"clientid\" = @ClientID, \"paymentinformation\" = @PaymentInformation, \"unstructureddata\" = @UnstructuredData, \"fido2publickey\" = @FIDO2PublicKey " + - "WHERE \"id\" = @Id", user); + case EnumUserStoreType.PostgreSQL: - break; - } + cnn.Execute( + "UPDATE \"users\" " + + "SET \"username\" = @UserName, \"passwordhash\" = @PasswordHash, " + + " \"email\" = @Email, \"emailconfirmed\" = @EmailConfirmed, \"phonenumber\" = @PhoneNumber, \"phonenumberconfirmed\" = @PhoneNumberConfirmed, " + + " \"lockoutenabled\" = @LockoutEnabled, \"accessfailedcount\" = @AccessFailedCount, \"lockoutenddateutc\" = @LockoutEndDateUtc, \"securitystamp\" = @SecurityStamp, \"twofactorenabled\" = @TwoFactorEnabled, " + + " \"clientid\" = @ClientID, \"paymentinformation\" = @PaymentInformation, \"unstructureddata\" = @UnstructuredData, \"fido2publickey\" = @FIDO2PublicKey, \"passwordchangedate\" = @PasswordChangeDate " + + "WHERE \"id\" = @Id", user); - // ★ 基本的に、以下のプロパティ更新には、プロパティ更新メソッド(UserManager.XXXX[PropertyName]Async)を使用する。 - // この際、ASP.NET Identity Frameworkにより、本メソッド(UserStore.UpdateAsync)が呼び出されることがあるもよう。 - // その際、二重実行により二重登録(制約により例外になる)が起き得るので、以下は、ココに実装しないことにした。 - // await this.UpdateRoles(user, tgtUser); - // await this.UpdateLogins(user, tgtUser); - // await this.UpdateClaims(user, tgtUser); + break; } - break; - } + // ★ 基本的に、以下のプロパティ更新には、プロパティ更新メソッド(UserManager.XXXX[PropertyName]Async)を使用する。 + // この際、ASP.NET Identity Frameworkにより、本メソッド(UserStore.UpdateAsync)が呼び出されることがあるもよう。 + // その際、二重実行により二重登録(制約により例外になる)が起き得るので、以下は、ココに実装しないことにした。 + // await this.UpdateRoles(user, tgtUser); + // await this.UpdateLogins(user, tgtUser); + // await this.UpdateClaims(user, tgtUser); + } - Logging.MyOperationTrace(string.Format("{0}({1}) was updated.", user.Id, user.UserName)); + break; } + + Logging.MyOperationTrace(string.Format("{0}({1}) was updated.", user.Id, user.UserName)); + //} } catch (Exception ex) { Logging.MySQLLogForEx(ex); } - return; + return Task.FromResult(0); } #region ユーザの関連情報の更新( Roles, Logins, Claims ) diff --git a/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ASPNETIdentity/FIDO2Extension/FIDO2Helper.cs b/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ASPNETIdentity/FIDO2Extension/FIDO2Helper.cs index 2cbbb02a..861ea413 100644 --- a/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ASPNETIdentity/FIDO2Extension/FIDO2Helper.cs +++ b/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ASPNETIdentity/FIDO2Extension/FIDO2Helper.cs @@ -93,9 +93,9 @@ public bool ValidateSignature( // Challengeの一致 // Load public key - RSACryptoServiceProvider rsaCryptoServiceProvider = + RSACryptoServiceProvider rsaCryptoServiceProvider = RS256_KeyConverter.JwkToProvider(this.PublicKey); - + // VerifyData ret = rsaCryptoServiceProvider.VerifyData( data, signatureBytes, diff --git a/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ASPNETIdentity/OAuth2Extension/OAuth2Helper.cs b/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ASPNETIdentity/OAuth2Extension/OAuth2Helper.cs index 28c961d9..5100bf68 100644 --- a/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ASPNETIdentity/OAuth2Extension/OAuth2Helper.cs +++ b/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ASPNETIdentity/OAuth2Extension/OAuth2Helper.cs @@ -52,8 +52,7 @@ using Newtonsoft.Json; -using Touryo.Infrastructure.Public.Str; -using Touryo.Infrastructure.Public.Security; +using Touryo.Infrastructure.Framework.Authentication; namespace MultiPurposeAuthSite.Models.ASPNETIdentity.OAuth2Extension { @@ -63,10 +62,10 @@ public class OAuth2Helper #region member variable /// Singleton (instance) - private static OAuth2Helper _oAuthHelper = new OAuth2Helper(); + private static OAuth2Helper _oAuth2Helper = new OAuth2Helper(); /// クライアント識別子情報 - private Dictionary> _oauthClientsInfo = null; + private Dictionary> _oauth2ClientsInfo = null; /// /// OAuth Server @@ -81,7 +80,7 @@ public class OAuth2Helper /// https://techinfoofmicrosofttech.osscons.jp/index.php?HttpClient%E3%81%AE%E9%A1%9E%E3%81%AE%E4%BD%BF%E3%81%84%E6%96%B9#l0c18008 /// Singletonで使うので、ここではstaticではない。 /// - private HttpClient _oAuthHttpClient = null; + private HttpClient _oAuth2HttpClient = null; #endregion @@ -91,10 +90,13 @@ public class OAuth2Helper private OAuth2Helper() { // クライアント識別子情報 - this._oauthClientsInfo = - JsonConvert.DeserializeObject>>(ASPNETIdentityConfig.OAuthClientsInformation); + this._oauth2ClientsInfo = + JsonConvert.DeserializeObject>>(ASPNETIdentityConfig.OAuth2ClientsInformation); // OAuth ServerにアクセスするためのHttpClient - this._oAuthHttpClient = HttpClientBuilder(EnumProxyType.Intranet); + this._oAuth2HttpClient = HttpClientBuilder(EnumProxyType.Intranet); + + // ライブラリを使用 + OAuth2AndOIDCClient.HttpClient = this._oAuth2HttpClient; } #endregion @@ -104,22 +106,22 @@ private OAuth2Helper() /// /// OauthClientsInfo /// - private Dictionary> OauthClientsInfo + private Dictionary> Oauth2ClientsInfo { get { - return this._oauthClientsInfo; + return this._oauth2ClientsInfo; } } /// /// OAuthHttpClient /// - private HttpClient OAuthHttpClient + private HttpClient OAuth2HttpClient { get { - return this._oAuthHttpClient; + return this._oAuth2HttpClient; } } @@ -131,14 +133,14 @@ private HttpClient OAuthHttpClient /// OAuthHelper public static OAuth2Helper GetInstance() { - return OAuth2Helper._oAuthHelper; + return OAuth2Helper._oAuth2Helper; } #endregion #region instanceメソッド - #region HttpClient + #region HTTP #region ClientBuilder @@ -177,9 +179,27 @@ private HttpClient HttpClientBuilder(EnumProxyType proxyType) #endregion - #region Access Token + #region 基本 4 フローのWebAPI + + /// + /// Authentication Code : codeからAccess Tokenを取得する。 + /// + /// TokenエンドポイントのUri + /// client_id + /// client_secret + /// redirect_uri + /// code + /// 結果のJSON文字列 + public async Task GetAccessTokenByCodeAsync( + Uri tokenEndpointUri, string client_id, string client_secret, string redirect_uri, string code) + { + return await OAuth2AndOIDCClient.GetAccessTokenByCodeAsync( + tokenEndpointUri, client_id, client_secret, redirect_uri, code); + } - /// 仲介コードからAccess Tokenを取得する。 + /// + /// PKCE : code, code_verifierからAccess Tokenを取得する。 + /// /// TokenエンドポイントのUri /// client_id /// client_secret @@ -190,54 +210,38 @@ private HttpClient HttpClientBuilder(EnumProxyType proxyType) public async Task GetAccessTokenByCodeAsync( Uri tokenEndpointUri, string client_id, string client_secret, string redirect_uri, string code, string code_verifier) { - // 4.1.3. アクセストークンリクエスト - // http://openid-foundation-japan.github.io/rfc6749.ja.html#token-req - - // 通信用の変数 - HttpRequestMessage httpRequestMessage = null; - HttpResponseMessage httpResponseMessage = null; - - // HttpRequestMessage (Method & RequestUri) - httpRequestMessage = new HttpRequestMessage - { - Method = HttpMethod.Post, - RequestUri = tokenEndpointUri, - }; - - // HttpRequestMessage (Headers & Content) - - httpRequestMessage.Headers.Authorization = new AuthenticationHeaderValue( - "Basic", - CustomEncode.ToBase64String(CustomEncode.StringToByte( - string.Format("{0}:{1}", client_id, client_secret), CustomEncode.us_ascii))); + return await OAuth2AndOIDCClient.GetAccessTokenByCodeAsync( + tokenEndpointUri, client_id, client_secret, redirect_uri, code, code_verifier); + } - if (string.IsNullOrEmpty(code_verifier)) - { - // 通常のアクセストークン・リクエスト - httpRequestMessage.Content = new FormUrlEncodedContent( - new Dictionary - { - { "grant_type", ASPNETIdentityConst.AuthorizationCodeGrantType }, - { "code", code }, - { "redirect_uri", HttpUtility.HtmlEncode(redirect_uri) }, - }); - } - else - { - // OAuth PKCEのアクセストークン・リクエスト - httpRequestMessage.Content = new FormUrlEncodedContent( - new Dictionary - { - { "grant_type", ASPNETIdentityConst.AuthorizationCodeGrantType }, - { "code", code }, - { "code_verifier", code_verifier }, - { "redirect_uri", HttpUtility.HtmlEncode(redirect_uri) }, - }); - } + /// + /// FAPI1 : code, code_verifierからAccess Tokenを取得する。 + /// + /// TokenエンドポイントのUri + /// redirect_uri + /// code + /// assertion + /// 結果のJSON文字列 + public async Task GetAccessTokenByCodeAsync( + Uri tokenEndpointUri, string redirect_uri, string code, string assertion) + { + return await OAuth2AndOIDCClient.GetAccessTokenByCodeAsync( + tokenEndpointUri, redirect_uri, code, assertion); + } - // HttpResponseMessage - httpResponseMessage = await _oAuthHttpClient.SendAsync(httpRequestMessage); - return await httpResponseMessage.Content.ReadAsStringAsync(); + /// + /// Client Credentials Grant + /// + /// TokenエンドポイントのUri + /// string + /// string + /// string + /// 結果のJSON文字列 + public async Task ClientCredentialsGrantAsync( + Uri tokenEndpointUri, string client_id, string client_secret, string scopes) + { + return await OAuth2AndOIDCClient.ClientCredentialsGrantAsync( + tokenEndpointUri, client_id, client_secret, scopes); } /// Refresh Tokenを使用してAccess Tokenを更新する。 @@ -249,44 +253,10 @@ public async Task GetAccessTokenByCodeAsync( public async Task UpdateAccessTokenByRefreshTokenAsync( Uri tokenEndpointUri, string client_id, string client_secret, string refreshToken) { - // 6. アクセストークンの更新 - // http://openid-foundation-japan.github.io/rfc6749.ja.html#token-refresh - - // 通信用の変数 - HttpRequestMessage httpRequestMessage = null; - HttpResponseMessage httpResponseMessage = null; - - // HttpRequestMessage (Method & RequestUri) - httpRequestMessage = new HttpRequestMessage - { - Method = HttpMethod.Post, - RequestUri = tokenEndpointUri, - }; - - // HttpRequestMessage (Headers & Content) - - httpRequestMessage.Headers.Authorization = new AuthenticationHeaderValue( - "Basic", - CustomEncode.ToBase64String(CustomEncode.StringToByte( - string.Format("{0}:{1}", client_id, client_secret), CustomEncode.us_ascii))); - - // HttpRequestMessage (Content) - httpRequestMessage.Content = new FormUrlEncodedContent( - new Dictionary - { - { "grant_type", ASPNETIdentityConst.RefreshTokenGrantType }, - { "refresh_token", refreshToken }, - }); - - // HttpResponseMessage - httpResponseMessage = await _oAuthHttpClient.SendAsync(httpRequestMessage); - return await httpResponseMessage.Content.ReadAsStringAsync(); + return await OAuth2AndOIDCClient.UpdateAccessTokenByRefreshTokenAsync( + tokenEndpointUri, client_id, client_secret, refreshToken); } - #endregion - - #region UserInfo - /// UserInfoエンドポイントで、認可ユーザのClaim情報を取得する。 /// accessToken /// 結果のJSON文字列(認可したユーザのClaim情報) @@ -295,34 +265,19 @@ public async Task GetUserInfoAsync(string accessToken) // 通信用の変数 // 認可したユーザのClaim情報を取得するWebAPI - Uri webApiEndpointUri = new Uri( - ASPNETIdentityConfig.OAuthResourceServerEndpointsRootURI - + ASPNETIdentityConfig.OAuthGetUserClaimsWebAPI); - - HttpRequestMessage httpRequestMessage = null; - HttpResponseMessage httpResponseMessage = null; + Uri userInfoUri = new Uri( + ASPNETIdentityConfig.OAuth2ResourceServerEndpointsRootURI + + ASPNETIdentityConfig.OAuth2GetUserClaimsWebAPI); - // HttpRequestMessage (Method & RequestUri) - httpRequestMessage = new HttpRequestMessage - { - Method = HttpMethod.Get, - RequestUri = webApiEndpointUri, - }; - - // HttpRequestMessage (Headers) - httpRequestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken); - - // HttpResponseMessage - httpResponseMessage = await _oAuthHttpClient.SendAsync(httpRequestMessage); - return await httpResponseMessage.Content.ReadAsStringAsync(); + return await OAuth2AndOIDCClient.GetUserInfoAsync(userInfoUri, accessToken); } #endregion - #region Extension + #region 拡張フローのWebAPI #region Revoke & Introspect - + /// Revokeエンドポイントで、Tokenを無効化する。 /// RevokeエンドポイントのUri /// client_id @@ -333,34 +288,8 @@ public async Task GetUserInfoAsync(string accessToken) public async Task RevokeTokenAsync( Uri revokeTokenEndpointUri, string client_id, string client_secret, string token, string token_type_hint) { - // 通信用の変数 - HttpRequestMessage httpRequestMessage = null; - HttpResponseMessage httpResponseMessage = null; - - // HttpRequestMessage (Method & RequestUri) - httpRequestMessage = new HttpRequestMessage - { - Method = HttpMethod.Post, - RequestUri = revokeTokenEndpointUri, - }; - - // HttpRequestMessage (Headers & Content) - - httpRequestMessage.Headers.Authorization = new AuthenticationHeaderValue( - "Basic", - CustomEncode.ToBase64String(CustomEncode.StringToByte( - string.Format("{0}:{1}", client_id, client_secret), CustomEncode.us_ascii))); - - httpRequestMessage.Content = new FormUrlEncodedContent( - new Dictionary - { - { "token", token }, - { "token_type_hint", token_type_hint }, - }); - - // HttpResponseMessage - httpResponseMessage = await _oAuthHttpClient.SendAsync(httpRequestMessage); - return await httpResponseMessage.Content.ReadAsStringAsync(); + return await OAuth2AndOIDCClient.RevokeTokenAsync( + revokeTokenEndpointUri, client_id, client_secret, token, token_type_hint); } /// Introspectエンドポイントで、Tokenを無効化する。 @@ -373,84 +302,12 @@ public async Task RevokeTokenAsync( public async Task IntrospectTokenAsync( Uri introspectTokenEndpointUri, string client_id, string client_secret, string token, string token_type_hint) { - // 通信用の変数 - HttpRequestMessage httpRequestMessage = null; - HttpResponseMessage httpResponseMessage = null; - - // HttpRequestMessage (Method & RequestUri) - httpRequestMessage = new HttpRequestMessage - { - Method = HttpMethod.Post, - RequestUri = introspectTokenEndpointUri, - }; - - // HttpRequestMessage (Headers & Content) - - httpRequestMessage.Headers.Authorization = new AuthenticationHeaderValue( - "Basic", - CustomEncode.ToBase64String(CustomEncode.StringToByte( - string.Format("{0}:{1}", client_id, client_secret), CustomEncode.us_ascii))); - - httpRequestMessage.Content = new FormUrlEncodedContent( - new Dictionary - { - { "token", token }, - { "token_type_hint", token_type_hint }, - }); - - // HttpResponseMessage - httpResponseMessage = await _oAuthHttpClient.SendAsync(httpRequestMessage); - return await httpResponseMessage.Content.ReadAsStringAsync(); + return await OAuth2AndOIDCClient.IntrospectTokenAsync( + introspectTokenEndpointUri, client_id, client_secret, token, token_type_hint); } #endregion - - #region Client Authentication Flow - - #region Client Credentials Flow - - /// - /// Tokenエンドポイントで、 - /// Client Credentialsグラント種別の要求を行う。 - /// TokenエンドポイントのUri - /// string - /// string - /// string - /// 結果のJSON文字列 - public async Task ClientCredentialsFlowAsync(Uri tokenEndpointUri, string client_id, string client_secret, string scopes) - { - // 通信用の変数 - HttpRequestMessage httpRequestMessage = null; - HttpResponseMessage httpResponseMessage = null; - - // HttpRequestMessage (Method & RequestUri) - httpRequestMessage = new HttpRequestMessage - { - Method = HttpMethod.Post, - RequestUri = tokenEndpointUri, - }; - - // HttpRequestMessage (Headers & Content) - - httpRequestMessage.Headers.Authorization = new AuthenticationHeaderValue( - "Basic", - CustomEncode.ToBase64String(CustomEncode.StringToByte( - string.Format("{0}:{1}", client_id, client_secret), CustomEncode.us_ascii))); - - httpRequestMessage.Content = new FormUrlEncodedContent( - new Dictionary - { - { "grant_type", ASPNETIdentityConst.ClientCredentialsGrantType }, - { "scope", scopes }, - }); - - // HttpResponseMessage - httpResponseMessage = await _oAuthHttpClient.SendAsync(httpRequestMessage); - return await httpResponseMessage.Content.ReadAsStringAsync(); - } - - #endregion - + #region JWT Bearer Token Flow /// @@ -461,35 +318,11 @@ public async Task ClientCredentialsFlowAsync(Uri tokenEndpointUri, strin /// 結果のJSON文字列 public async Task JwtBearerTokenFlowAsync(Uri token2EndpointUri, string assertion) { - // 通信用の変数 - HttpRequestMessage httpRequestMessage = null; - HttpResponseMessage httpResponseMessage = null; - - // HttpRequestMessage (Method & RequestUri) - httpRequestMessage = new HttpRequestMessage - { - Method = HttpMethod.Post, - RequestUri = token2EndpointUri, - }; - - // HttpRequestMessage (Headers & Content) - - httpRequestMessage.Content = new FormUrlEncodedContent( - new Dictionary - { - { "grant_type", ASPNETIdentityConst.JwtBearerTokenFlowGrantType }, - { "assertion", assertion }, - }); - - // HttpResponseMessage - httpResponseMessage = await _oAuthHttpClient.SendAsync(httpRequestMessage); - return await httpResponseMessage.Content.ReadAsStringAsync(); + return await OAuth2AndOIDCClient.JwtBearerTokenFlowAsync(token2EndpointUri, assertion); } #endregion - - #endregion - + #endregion #region OAuth2(ResourcesServer)WebAPI @@ -499,14 +332,14 @@ public async Task JwtBearerTokenFlowAsync(Uri token2EndpointUri, string /// 通貨 /// 料金 /// 結果のJSON文字列 - public async Task CallOAuthChageToUserWebAPIAsync( + public async Task CallOAuth2ChageToUserWebAPIAsync( string accessToken, string currency, string amount) { // 通信用の変数 // 課金用のWebAPI Uri webApiEndpointUri = new Uri( - ASPNETIdentityConfig.OAuthAuthorizationServerEndpointsRootURI + ASPNETIdentityConfig.OAuth2AuthorizationServerEndpointsRootURI + ASPNETIdentityConfig.TestChageToUserWebAPI); HttpRequestMessage httpRequestMessage = null; @@ -520,7 +353,7 @@ public async Task CallOAuthChageToUserWebAPIAsync( }; // HttpRequestMessage (Headers & Content) - httpRequestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken); + httpRequestMessage.Headers.Authorization = new AuthenticationHeaderValue(OAuth2AndOIDCConst.Bearer, accessToken); httpRequestMessage.Content = new FormUrlEncodedContent( new Dictionary { @@ -530,7 +363,7 @@ public async Task CallOAuthChageToUserWebAPIAsync( httpRequestMessage.Content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded"); // HttpResponseMessage - httpResponseMessage = await _oAuthHttpClient.SendAsync(httpRequestMessage); + httpResponseMessage = await _oAuth2HttpClient.SendAsync(httpRequestMessage); return await httpResponseMessage.Content.ReadAsStringAsync(); } @@ -538,9 +371,7 @@ public async Task CallOAuthChageToUserWebAPIAsync( #endregion - #region OAuth2関連ヘルパ - - #region Credential取得 + #region Credential #region Client authentication @@ -552,9 +383,9 @@ public string GetClientSecret(string client_id) client_id = client_id ?? ""; // *.config内を検索 - if (this.OauthClientsInfo.ContainsKey(client_id)) + if (this.Oauth2ClientsInfo.ContainsKey(client_id)) { - return this.OauthClientsInfo[client_id]["client_secret"]; + return this.Oauth2ClientsInfo[client_id]["client_secret"]; } // oAuth2Dataを検索 @@ -583,15 +414,15 @@ public string GetClientsRedirectUri(string client_id, string response_type) response_type = response_type ?? ""; // *.config内を検索 - if (this.OauthClientsInfo.ContainsKey(client_id)) + if (this.Oauth2ClientsInfo.ContainsKey(client_id)) { - if (response_type.ToLower() == ASPNETIdentityConst.AuthorizationCodeResponseType) + if (response_type.ToLower() == OAuth2AndOIDCConst.AuthorizationCodeResponseType) { - return this.OauthClientsInfo[client_id]["redirect_uri_code"]; + return this.Oauth2ClientsInfo[client_id]["redirect_uri_code"]; } - else if (response_type.ToLower() == ASPNETIdentityConst.ImplicitResponseType) + else if (response_type.ToLower() == OAuth2AndOIDCConst.ImplicitResponseType) { - return this.OauthClientsInfo[client_id]["redirect_uri_token"]; + return this.Oauth2ClientsInfo[client_id]["redirect_uri_token"]; } } @@ -602,11 +433,11 @@ public string GetClientsRedirectUri(string client_id, string response_type) { ManageAddOAuth2DataViewModel model = JsonConvert.DeserializeObject(oAuth2Data); - if (response_type.ToLower() == ASPNETIdentityConst.AuthorizationCodeResponseType) + if (response_type.ToLower() == OAuth2AndOIDCConst.AuthorizationCodeResponseType) { return model.RedirectUriCode; } - else if (response_type.ToLower() == ASPNETIdentityConst.ImplicitResponseType) + else if (response_type.ToLower() == OAuth2AndOIDCConst.ImplicitResponseType) { return model.RedirectUriToken; } @@ -623,9 +454,9 @@ public string GetJwtAssertionPublickey(string client_id) client_id = client_id ?? ""; // *.config内を検索 - if (this.OauthClientsInfo.ContainsKey(client_id)) + if (this.Oauth2ClientsInfo.ContainsKey(client_id)) { - return this.OauthClientsInfo[client_id]["jwt_assertion_publickey"]; + return this.Oauth2ClientsInfo[client_id]["jwt_assertion_publickey"]; } // oAuth2Dataを検索 @@ -658,9 +489,9 @@ public string GetClientName(string client_id) client_id = client_id ?? ""; // *.config内を検索 - if (this.OauthClientsInfo.ContainsKey(client_id)) + if (this.Oauth2ClientsInfo.ContainsKey(client_id)) { - return this.OauthClientsInfo[client_id]["client_name"]; + return this.Oauth2ClientsInfo[client_id]["client_name"]; } // oAuth2Dataを検索 @@ -679,10 +510,10 @@ public string GetClientName(string client_id) public string GetClientIdByName(string clientName) { // *.config内を検索 - foreach (string clientId in this.OauthClientsInfo.Keys) + foreach (string clientId in this.Oauth2ClientsInfo.Keys) { Dictionary client - = this.OauthClientsInfo[clientId]; + = this.Oauth2ClientsInfo[clientId]; string temp = client["client_name"]; if (temp.ToLower() == clientName.ToLower()) @@ -702,9 +533,7 @@ ApplicationUserManager userManager #endregion #endregion - - #endregion - + #endregion #region staticメソッド @@ -717,18 +546,18 @@ ApplicationUserManager userManager public static IEnumerable FilterClaimAtAuth(IEnumerable scopes) { List temp = new List(); - temp.Add(ASPNETIdentityConst.Scope_Auth); + temp.Add(OAuth2AndOIDCConst.Scope_Auth); // フィルタ・コード foreach (string s in scopes) { - if (s == ASPNETIdentityConst.Scope_Openid) + if (s == OAuth2AndOIDCConst.Scope_Openid) { - temp.Add(ASPNETIdentityConst.Scope_Openid); + temp.Add(OAuth2AndOIDCConst.Scope_Openid); } - else if (s == ASPNETIdentityConst.Scope_Userid) + else if (s == OAuth2AndOIDCConst.Scope_UserID) { - temp.Add(ASPNETIdentityConst.Scope_Userid); + temp.Add(OAuth2AndOIDCConst.Scope_UserID); } } @@ -753,13 +582,13 @@ public static ClaimsIdentity AddClaim(ClaimsIdentity claims, #region 標準 - claims.AddClaim(new Claim(ASPNETIdentityConst.Claim_Issuer, ASPNETIdentityConfig.OAuthIssuerId)); - claims.AddClaim(new Claim(ASPNETIdentityConst.Claim_Audience, client_id)); + claims.AddClaim(new Claim(OAuth2AndOIDCConst.Claim_Issuer, ASPNETIdentityConfig.OAuth2IssuerId)); + claims.AddClaim(new Claim(OAuth2AndOIDCConst.Claim_Audience, client_id)); foreach (string scope in scopes) { // その他のscopeは、Claimの下記urnに組み込む。 - claims.AddClaim(new Claim(ASPNETIdentityConst.Claim_Scope, scope)); + claims.AddClaim(new Claim(OAuth2AndOIDCConst.Claim_Scopes, scope)); } #endregion @@ -769,11 +598,11 @@ public static ClaimsIdentity AddClaim(ClaimsIdentity claims, // OpenID Connect if (string.IsNullOrEmpty(nonce)) { - claims.AddClaim(new Claim(ASPNETIdentityConst.Claim_Nonce, state)); + claims.AddClaim(new Claim(OAuth2AndOIDCConst.Claim_Nonce, state)); } else { - claims.AddClaim(new Claim(ASPNETIdentityConst.Claim_Nonce, nonce)); + claims.AddClaim(new Claim(OAuth2AndOIDCConst.Claim_Nonce, nonce)); } #endregion @@ -782,24 +611,7 @@ public static ClaimsIdentity AddClaim(ClaimsIdentity claims, } #endregion - - #region PKCE_CodeChallengeMethod - - /// - /// code_challenge_method=S256 - /// BASE64URL-ENCODE(SHA256(ASCII(code_verifier))) - /// string - /// code_challenge - public static string PKCE_S256_CodeChallengeMethod(string code_verifier) - { - return CustomEncode.ToBase64UrlString( - GetHash.GetHashBytes( - CustomEncode.StringToByte(code_verifier, CustomEncode.us_ascii), - EnumHashAlgorithm.SHA256Managed)); - } - - #endregion - + #endregion } } \ No newline at end of file diff --git a/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ASPNETIdentity/OIDCFilter/ClientCredentialsFilter.cs b/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ASPNETIdentity/OIDCFilter/ClientCredentialsFilter.cs index 3e58d9ee..6e4363e4 100644 --- a/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ASPNETIdentity/OIDCFilter/ClientCredentialsFilter.cs +++ b/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ASPNETIdentity/OIDCFilter/ClientCredentialsFilter.cs @@ -39,6 +39,8 @@ using Newtonsoft.Json; +using Touryo.Infrastructure.Framework.Authentication; + namespace MultiPurposeAuthSite.Models.ASPNETIdentity.OIDCFilter { /// @@ -130,9 +132,9 @@ public override void Flush() Dictionary accessTokenResponse = JsonConvert.DeserializeObject>(content); // refresh_tokenを削除 - if (accessTokenResponse.ContainsKey("refresh_token")) + if (accessTokenResponse.ContainsKey(OAuth2AndOIDCConst.RefreshToken)) { - accessTokenResponse.Remove("refresh_token"); + accessTokenResponse.Remove(OAuth2AndOIDCConst.RefreshToken); bb = enc.GetBytes(JsonConvert.SerializeObject(accessTokenResponse)); } } diff --git a/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ASPNETIdentity/OIDCFilter/HashClaimType.cs b/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ASPNETIdentity/OIDCFilter/HashClaimType.cs deleted file mode 100644 index 74a69312..00000000 --- a/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ASPNETIdentity/OIDCFilter/HashClaimType.cs +++ /dev/null @@ -1,54 +0,0 @@ -//********************************************************************************** -//* Copyright (C) 2017 Hitachi Solutions,Ltd. -//********************************************************************************** - -#region Apache License -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#endregion - -//********************************************************************************** -//* クラス名 :HashClaimType enum -//* クラス日本語名 :HashClaimType 列挙型 -//* -//* 作成日時 :- -//* 作成者 :- -//* 更新履歴 :- -//* -//* 日時 更新者 内容 -//* ---------- ---------------- ------------------------------------------------- -//* 2018/01/26 西野 大介 新規 -//********************************************************************************** - -namespace MultiPurposeAuthSite.Models.ASPNETIdentity.OIDCFilter -{ - /// - /// HashClaimのタイプ - /// ・None - /// ・at_hash - /// ・c_hash - /// ・Both - /// - public enum HashClaimType - { - /// HashClaim無し - None, - /// at_hashを付与 - AtHash, - /// c_hashを付与 - CHash, - /// at_hash, c_hashの両方を付与 - Both - } -} \ No newline at end of file diff --git a/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ASPNETIdentity/OIDCFilter/OidcTokenEditor.cs b/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ASPNETIdentity/OIDCFilter/OidcTokenEditor.cs index a746cbf8..b46bb0f7 100644 --- a/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ASPNETIdentity/OIDCFilter/OidcTokenEditor.cs +++ b/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ASPNETIdentity/OIDCFilter/OidcTokenEditor.cs @@ -42,8 +42,7 @@ using Newtonsoft.Json; using Newtonsoft.Json.Linq; -using Touryo.Infrastructure.Public.Str; -using Touryo.Infrastructure.Public.Util; +using Touryo.Infrastructure.Framework.Authentication; using Touryo.Infrastructure.Public.Security; namespace MultiPurposeAuthSite.Models.ASPNETIdentity.OIDCFilter @@ -73,7 +72,7 @@ public class OidcTokenEditor /// /// Hybrid Flow対応なので、scopeを制限してもイイ。 /// - public static string CreateAccessTokenPayload(AuthenticationTicket ticket) + public static string CreateAccessTokenPayloadFromAuthenticationTicket(AuthenticationTicket ticket) { // チェック if (ticket == null) @@ -87,19 +86,19 @@ public static string CreateAccessTokenPayload(AuthenticationTicket ticket) foreach (Claim c in ticket.Identity.Claims) { - if (c.Type == ASPNETIdentityConst.Claim_Issuer) + if (c.Type == OAuth2AndOIDCConst.Claim_Issuer) { - authTokenClaimSet.Add("iss", c.Value); + authTokenClaimSet.Add(OAuth2AndOIDCConst.iss, c.Value); } - else if (c.Type == ASPNETIdentityConst.Claim_Audience) + else if (c.Type == OAuth2AndOIDCConst.Claim_Audience) { - authTokenClaimSet.Add("aud", c.Value); + authTokenClaimSet.Add(OAuth2AndOIDCConst.aud, c.Value); } - else if (c.Type == ASPNETIdentityConst.Claim_Nonce) + else if (c.Type == OAuth2AndOIDCConst.Claim_Nonce) { - authTokenClaimSet.Add("nonce", c.Value); + authTokenClaimSet.Add(OAuth2AndOIDCConst.nonce, c.Value); } - else if (c.Type == ASPNETIdentityConst.Claim_Scope) + else if (c.Type == OAuth2AndOIDCConst.Claim_Scopes) { scopes.Add(c.Value); } @@ -110,24 +109,24 @@ public static string CreateAccessTokenPayload(AuthenticationTicket ticket) } // Resource Owner認証の場合、Resource Ownerの名称 - authTokenClaimSet.Add("sub", ticket.Identity.Name); + authTokenClaimSet.Add(OAuth2AndOIDCConst.sub, ticket.Identity.Name); - #region authTokenClaimSet.Add("exp", ・・・ + #region authTokenClaimSet.Add(OAuth2AndOIDCConst.exp, ・・・ // ticketの値を使用(これは、codeのexpっぽい。300秒になっているのでNG。) - //authTokenClaimSet.Add("exp", ticket.Properties.ExpiresUtc.Value.ToUnixTimeSeconds().ToString()); + //authTokenClaimSet.Add(OAuth2AndOIDCConst.exp, ticket.Properties.ExpiresUtc.Value.ToUnixTimeSeconds().ToString()); // この時点では空にしておく。 - authTokenClaimSet.Add("exp", ""); + authTokenClaimSet.Add(OAuth2AndOIDCConst.exp, ""); #endregion - authTokenClaimSet.Add("nbf", DateTimeOffset.Now.ToUnixTimeSeconds().ToString()); - authTokenClaimSet.Add("iat", ticket.Properties.IssuedUtc.Value.ToUnixTimeSeconds().ToString()); - authTokenClaimSet.Add("jti", Guid.NewGuid().ToString("N")); + authTokenClaimSet.Add(OAuth2AndOIDCConst.nbf, DateTimeOffset.Now.ToUnixTimeSeconds().ToString()); + authTokenClaimSet.Add(OAuth2AndOIDCConst.iat, ticket.Properties.IssuedUtc.Value.ToUnixTimeSeconds().ToString()); + authTokenClaimSet.Add(OAuth2AndOIDCConst.jti, Guid.NewGuid().ToString("N")); // ★ Hybrid Flow対応なので、scopeを制限してもイイ。 - authTokenClaimSet.Add("scopes", scopes); + authTokenClaimSet.Add(OAuth2AndOIDCConst.scopes, scopes); // scope値によって、返す値を変更する。 // ココでは返さない(別途ユーザ取得処理を実装してもイイ)。 @@ -136,185 +135,69 @@ public static string CreateAccessTokenPayload(AuthenticationTicket ticket) } /// - /// ProtectFromPayload + /// ProtectFromAccessTokenPayload /// Hybrid Flow対応(access_token_payloadを処理) /// /// AccessTokenのPayload /// Hybrid Flowのtokenに対応したexp - /// - public static string ProtectFromPayload(string access_token_payload, ulong customExp) + /// IdToken + public static string ProtectFromAccessTokenPayload(string access_token_payload, ulong customExp) { string json = ""; - string jwt = ""; + //string jws = ""; // ticketの値を使用(これは、codeのexpっぽい。300秒になっているのでNG。) - //authTokenClaimSet.Add("exp", ticket.Properties.ExpiresUtc.Value.ToUnixTimeSeconds().ToString()); - //authTokenClaimSet.Add("exp", DateTimeOffset.Now.AddSeconds(customExp).ToUnixTimeSeconds().ToString()); + //authTokenClaimSet.Add(OAuth2AndOIDCConst.exp, ticket.Properties.ExpiresUtc.Value.ToUnixTimeSeconds().ToString()); + //authTokenClaimSet.Add(OAuth2AndOIDCConst.exp, DateTimeOffset.Now.AddSeconds(customExp).ToUnixTimeSeconds().ToString()); #region JSON編集 // access_token_payloadのDictionary化 - Dictionary dic = + Dictionary payload = JsonConvert.DeserializeObject>(access_token_payload); // ★ customExpの値を使用する。 - dic["exp"] = DateTimeOffset.Now.AddSeconds(customExp).ToUnixTimeSeconds().ToString(); + payload[OAuth2AndOIDCConst.exp] = DateTimeOffset.Now.AddSeconds(customExp).ToUnixTimeSeconds().ToString(); // ★ Hybrid Flow対応なので、scopeを制限してもイイ。 - dic["scopes"] = dic["scopes"]; + payload[OAuth2AndOIDCConst.scopes] = payload[OAuth2AndOIDCConst.scopes]; - json = JsonConvert.SerializeObject(dic); + json = JsonConvert.SerializeObject(payload); #endregion - #region JWT化 + #region JWS化 - JWT_RS256 jwtRS256 = null; + JWS_RS256_X509 jwsRS256 = null; // 署名 - jwtRS256 = new JWT_RS256(ASPNETIdentityConfig.OAuthJWT_pfx, ASPNETIdentityConfig.OAuthJWTPassword, + jwsRS256 = new JWS_RS256_X509(ASPNETIdentityConfig.OAuth2JWT_pfx, ASPNETIdentityConfig.OAuth2JWTPassword, X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet); - jwt = jwtRS256.Create(json); + // JWSHeaderのセット + // kid : https://openid-foundation-japan.github.io/rfc7638.ja.html#Example + Dictionary jwk = + JsonConvert.DeserializeObject>( + RS256_KeyConverter.X509PfxToJwkPublicKey(ASPNETIdentityConfig.OAuth2JWT_pfx, ASPNETIdentityConfig.OAuth2JWTPassword)); - // 検証 - jwtRS256 = new JWT_RS256(ASPNETIdentityConfig.OAuthJWT_cer, ASPNETIdentityConfig.OAuthJWTPassword, - X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet); + jwsRS256.JWSHeader.kid = jwk[JwtConst.kid]; + jwsRS256.JWSHeader.jku = ASPNETIdentityConfig.OAuth2AuthorizationServerEndpointsRootURI + OAuth2AndOIDCParams.JwkSetUri; - if (jwtRS256.Verify(jwt)) - { - return jwt; // 検証できた。 - } - else - { - return ""; // 検証できなかった。 - } + return jwsRS256.Create(json); - #endregion - } + //// 検証 + //jwsRS256 = new JWS_RS256_X509(OAuth2AndOIDCParams.RS256Cer, ASPNETIdentityConfig.OAuth2JWTPassword, + // X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet); - #endregion + //if (jwsRS256.Verify(jws)) + //{ + // return jws; // 検証できた。 + //} + //else + //{ + // return ""; // 検証できなかった。 + //} - #region IdToken - - /// - /// ChangeToIdTokenFromAccessToken - /// OIDC対応(AccessTokenからIdTokenを生成) - /// - /// string - /// string - /// HashClaimType - /// IdToken - /// - /// OIDC対応 - /// - - public static string ChangeToIdTokenFromAccessToken(string access_token, string code, HashClaimType hct) - { - if (access_token.Contains(".")) - { - string[] temp = access_token.Split('.'); - string json = CustomEncode.ByteToString(CustomEncode.FromBase64UrlString(temp[1]), CustomEncode.UTF_8); - Dictionary authTokenClaimSet = JsonConvert.DeserializeObject>(json); - - // ・access_tokenがJWTで、payloadに"nonce" and "scope=openidクレームが存在する場合、 - if (authTokenClaimSet.ContainsKey("nonce") - && authTokenClaimSet.ContainsKey("scopes")) - { - JArray scopes = (JArray)authTokenClaimSet["scopes"]; - - // ・OpenID Connect : response_type=codeに対応する。 - if (scopes.Any(x => x.ToString() == ASPNETIdentityConst.Scope_Openid)) - { - //・payloadからscopeを削除する。 - authTokenClaimSet.Remove("scopes"); - - //・payloadにat_hash, c_hashを追加する。 - switch (hct) - { - case HashClaimType.None: - break; - - case HashClaimType.AtHash: - // at_hash - authTokenClaimSet.Add( - "at_hash", - OidcTokenEditor.CreateHash(access_token)); - break; - - case HashClaimType.CHash: - // c_hash - authTokenClaimSet.Add( - "c_hash", - OidcTokenEditor.CreateHash(code)); - break; - - case HashClaimType.Both: - // at_hash, c_hash - authTokenClaimSet.Add( - "at_hash", - OidcTokenEditor.CreateHash(access_token)); - authTokenClaimSet.Add( - "c_hash", - OidcTokenEditor.CreateHash(code)); - break; - } - - //・編集したpayloadを再度JWTとして署名する。 - string newPayload = JsonConvert.SerializeObject(authTokenClaimSet); - JWT_RS256 jwtRS256 = null; - - // 署名 - jwtRS256 = new JWT_RS256(ASPNETIdentityConfig.OAuthJWT_pfx, ASPNETIdentityConfig.OAuthJWTPassword, - X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet); - - string id_token = jwtRS256.Create(newPayload); - - // 検証 - jwtRS256 = new JWT_RS256(ASPNETIdentityConfig.OAuthJWT_cer, ASPNETIdentityConfig.OAuthJWTPassword, - X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet); - - if (jwtRS256.Verify(id_token)) - { - // 検証できた。 - return id_token; - } - else - { - // 検証できなかった。 - } - } - else - { - // OIDCでない。 - } - } - else - { - // OIDCでない。 - } - } - else - { - // JWTでない。 - } - - return ""; - } - - /// - /// SHA256でat_hash, c_hashを作成。 - /// (現時点でRS256固定になっているので) - /// - /// hash - public static string CreateHash(string input) - { - // ID Token の JOSE Header にある alg Header Parameterのアルゴリズムで使用されるハッシュアルゴリズムを用い、 - // input(access_token や code) のASCII オクテット列からハッシュ値を求め、左半分を base64url エンコードした値。 - return CustomEncode.ToBase64UrlString( - PubCmnFunction.ShortenByteArray( - GetHash.GetHashBytes( - CustomEncode.StringToByte(input, CustomEncode.us_ascii), - EnumHashAlgorithm.SHA256Managed), (256 / 2))); + #endregion } #endregion diff --git a/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ASPNETIdentity/OIDCFilter/OpenIDConnectCodeFilter.cs b/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ASPNETIdentity/OIDCFilter/OpenIDConnectCodeFilter.cs index 746ea767..5b4e20a5 100644 --- a/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ASPNETIdentity/OIDCFilter/OpenIDConnectCodeFilter.cs +++ b/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ASPNETIdentity/OIDCFilter/OpenIDConnectCodeFilter.cs @@ -39,6 +39,8 @@ using Newtonsoft.Json; +using Touryo.Infrastructure.Framework.Authentication; + namespace MultiPurposeAuthSite.Models.ASPNETIdentity.OIDCFilter { /// @@ -127,17 +129,22 @@ public override void Flush() string content = enc.GetString(bb); // JSON形式なので、JsonConvertでaccess_tokenを抜き出す。 - Dictionary accessTokenResponse = JsonConvert.DeserializeObject>(content); + Dictionary accessTokenResponse = + JsonConvert.DeserializeObject>(content); // access_tokenを - if (accessTokenResponse.ContainsKey("access_token")) + if (accessTokenResponse.ContainsKey(OAuth2AndOIDCConst.AccessToken)) { - string access_token = (string)accessTokenResponse["access_token"]; - string id_token = OidcTokenEditor.ChangeToIdTokenFromAccessToken(access_token, "", HashClaimType.None); + string access_token = (string)accessTokenResponse[OAuth2AndOIDCConst.AccessToken]; + + string id_token = IdToken.ChangeToIdTokenFromAccessToken( + access_token, "", "", HashClaimType.None, + ASPNETIdentityConfig.OAuth2JWT_pfx, ASPNETIdentityConfig.OAuth2JWTPassword); + if (!string.IsNullOrEmpty(id_token)) { // responseにid_tokenとして、このJWTを追加する。 - accessTokenResponse.Add("id_token", id_token); + accessTokenResponse.Add(OAuth2AndOIDCConst.IDToken, id_token); bb = enc.GetBytes(JsonConvert.SerializeObject(accessTokenResponse)); } } diff --git a/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ASPNETIdentity/OIDCFilter/OpenIDConnectModule.cs b/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ASPNETIdentity/OIDCFilter/OpenIDConnectModule.cs index c69895f4..d7740a16 100644 --- a/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ASPNETIdentity/OIDCFilter/OpenIDConnectModule.cs +++ b/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ASPNETIdentity/OIDCFilter/OpenIDConnectModule.cs @@ -38,8 +38,7 @@ using System.Web; -using Microsoft.Owin.Security; - +using Touryo.Infrastructure.Framework.Authentication; using Touryo.Infrastructure.Public.Str; namespace MultiPurposeAuthSite.Models.ASPNETIdentity.OIDCFilter @@ -165,27 +164,27 @@ private void OnBeginRequest(object sender, EventArgs e) string path = context.Request.Url.AbsolutePath; - if (path.IndexOf(ASPNETIdentityConfig.OAuthBearerTokenEndpoint2) == -1 - && path.IndexOf(ASPNETIdentityConfig.OAuthBearerTokenEndpoint) != -1) + if (path.IndexOf(ASPNETIdentityConfig.OAuth2BearerTokenEndpoint2) == -1 + && path.IndexOf(ASPNETIdentityConfig.OAuth2BearerTokenEndpoint) != -1) { - if (context.Request.Form["grant_type"] == ASPNETIdentityConst.RefreshTokenGrantType) + if (context.Request.Form[OAuth2AndOIDCConst.grant_type] == OAuth2AndOIDCConst.RefreshTokenGrantType) { // なにもしない } - else if (context.Request.Form["grant_type"] == ASPNETIdentityConst.ResourceOwnerPasswordCredentialsGrantType) + else if (context.Request.Form[OAuth2AndOIDCConst.grant_type] == OAuth2AndOIDCConst.ResourceOwnerPasswordCredentialsGrantType) { // なにもしない } - else if (context.Request.Form["grant_type"] == ASPNETIdentityConst.ClientCredentialsGrantType) + else if (context.Request.Form[OAuth2AndOIDCConst.grant_type] == OAuth2AndOIDCConst.ClientCredentialsGrantType) { // Refresh Tokenの削除 context.Response.Filter = new ClientCredentialsFilter(context); } - else if (context.Request.Form["grant_type"] == ASPNETIdentityConst.ImplicitGrantType) + else if (context.Request.Form[OAuth2AndOIDCConst.grant_type] == OAuth2AndOIDCConst.ImplicitGrantType) { // ↓OnPreSendRequestHeadersで処理 } - else if (context.Request.Form["grant_type"] == ASPNETIdentityConst.AuthorizationCodeGrantType) + else if (context.Request.Form[OAuth2AndOIDCConst.grant_type] == OAuth2AndOIDCConst.AuthorizationCodeGrantType) { // OpenID Connect の "response_type=code"に対応したレスポンスに書き換え context.Response.Filter = new OpenIDConnectCodeFilter(context); @@ -217,8 +216,8 @@ private void OnAuthorizeRequest(object sender, EventArgs e) string virtualPath = path.Substring(path.IndexOf(context.Request.ApplicationPath)); this.OriginalVirtualPath = virtualPath + orgQuery; - if (path.IndexOf(ASPNETIdentityConfig.OAuthAuthorizeEndpoint2) == -1 - && path.IndexOf(ASPNETIdentityConfig.OAuthAuthorizeEndpoint) != -1) + if (path.IndexOf(ASPNETIdentityConfig.OAuth2AuthorizeEndpoint2) == -1 + && path.IndexOf(ASPNETIdentityConfig.OAuth2AuthorizeEndpoint) != -1) { string pattern = ""; @@ -249,11 +248,11 @@ private void OnAuthorizeRequest(object sender, EventArgs e) // [response_type=id_token token] is_id_token_token = responseType.StartsWith( - CustomEncode.UrlEncode(ASPNETIdentityConst.OidcImplicit2_ResponseType)); + CustomEncode.UrlEncode(OAuth2AndOIDCConst.OidcImplicit2_ResponseType)); if (!is_id_token_token) { // [response_type=token] - is_id_token = responseType.StartsWith(ASPNETIdentityConst.OidcImplicit1_ResponseType); + is_id_token = responseType.StartsWith(OAuth2AndOIDCConst.OidcImplicit1_ResponseType); } // OIDC Hybrid @@ -263,16 +262,16 @@ private void OnAuthorizeRequest(object sender, EventArgs e) // [response_type=code id_token token] is_code_id_token_token = responseType.StartsWith( - CustomEncode.UrlEncode(ASPNETIdentityConst.OidcHybrid3_ResponseType)); + CustomEncode.UrlEncode(OAuth2AndOIDCConst.OidcHybrid3_ResponseType)); if (!is_code_id_token_token) { // [response_type=code id_token] is_code_id_token = responseType.StartsWith( - CustomEncode.UrlEncode(ASPNETIdentityConst.OidcHybrid2_IdToken_ResponseType)); + CustomEncode.UrlEncode(OAuth2AndOIDCConst.OidcHybrid2_IdToken_ResponseType)); // [response_type=code token] is_code_token = responseType.StartsWith( - CustomEncode.UrlEncode(ASPNETIdentityConst.OidcHybrid2_Token_ResponseType)); + CustomEncode.UrlEncode(OAuth2AndOIDCConst.OidcHybrid2_Token_ResponseType)); } #endregion @@ -286,15 +285,15 @@ private void OnAuthorizeRequest(object sender, EventArgs e) { this.RewritedResponseTypeFrom_IdToken = true; reWritedQuery = reWritedQuery.Replace( - "response_type=" + ASPNETIdentityConst.OidcImplicit1_ResponseType, - "response_type=" + ASPNETIdentityConst.ImplicitResponseType); + "response_type=" + OAuth2AndOIDCConst.OidcImplicit1_ResponseType, + "response_type=" + OAuth2AndOIDCConst.ImplicitResponseType); } else if (is_id_token_token) { this.RewritedResponseTypeFrom_IdTokenToken = true; reWritedQuery = reWritedQuery.Replace( - "response_type=" + CustomEncode.UrlEncode(ASPNETIdentityConst.OidcImplicit2_ResponseType), - "response_type=" + ASPNETIdentityConst.ImplicitResponseType); + "response_type=" + CustomEncode.UrlEncode(OAuth2AndOIDCConst.OidcImplicit2_ResponseType), + "response_type=" + OAuth2AndOIDCConst.ImplicitResponseType); } } else if (is_code_id_token || is_code_token || is_code_id_token_token) @@ -304,22 +303,22 @@ private void OnAuthorizeRequest(object sender, EventArgs e) { this.RewritedResponseTypeFrom_CodeIdToken = true; reWritedQuery = reWritedQuery.Replace( - "response_type=" + CustomEncode.UrlEncode(ASPNETIdentityConst.OidcHybrid2_IdToken_ResponseType), - "response_type=" + ASPNETIdentityConst.AuthorizationCodeResponseType); + "response_type=" + CustomEncode.UrlEncode(OAuth2AndOIDCConst.OidcHybrid2_IdToken_ResponseType), + "response_type=" + OAuth2AndOIDCConst.AuthorizationCodeResponseType); } else if (is_code_token) { this.RewritedResponseTypeFrom_CodeToken = true; reWritedQuery = reWritedQuery.Replace( - "response_type=" + CustomEncode.UrlEncode(ASPNETIdentityConst.OidcHybrid2_Token_ResponseType), - "response_type=" + ASPNETIdentityConst.AuthorizationCodeResponseType); + "response_type=" + CustomEncode.UrlEncode(OAuth2AndOIDCConst.OidcHybrid2_Token_ResponseType), + "response_type=" + OAuth2AndOIDCConst.AuthorizationCodeResponseType); } else if (is_code_id_token_token) { this.RewritedResponseTypeFrom_CodeIdTokenToken = true; reWritedQuery = reWritedQuery.Replace( - "response_type=" + CustomEncode.UrlEncode(ASPNETIdentityConst.OidcHybrid3_ResponseType), - "response_type=" + ASPNETIdentityConst.AuthorizationCodeResponseType); + "response_type=" + CustomEncode.UrlEncode(OAuth2AndOIDCConst.OidcHybrid3_ResponseType), + "response_type=" + OAuth2AndOIDCConst.AuthorizationCodeResponseType); } } else @@ -345,9 +344,9 @@ private void OnAuthorizeRequest(object sender, EventArgs e) //bool is_fragment = false; bool is_form_post = false; - //is_query = responseMode.StartsWith("query"); - //is_fragment = responseMode.StartsWith("fragment"); - is_form_post = responseMode.StartsWith("form_post"); + //is_query = responseMode.StartsWith(OAuth2AndOIDCConst.query); + //is_fragment = responseMode.StartsWith(OAuth2AndOIDCConst.fragment); + is_form_post = responseMode.StartsWith(OAuth2AndOIDCConst.form_post); if (is_form_post) { @@ -410,8 +409,8 @@ private void OnPreSendRequestHeaders(object sender, EventArgs e) #endregion - if (context.Request.Url.AbsolutePath.IndexOf(ASPNETIdentityConfig.OAuthAuthorizeEndpoint2) == -1 - && context.Request.Url.AbsolutePath.IndexOf(ASPNETIdentityConfig.OAuthAuthorizeEndpoint) != -1) + if (context.Request.Url.AbsolutePath.IndexOf(ASPNETIdentityConfig.OAuth2AuthorizeEndpoint2) == -1 + && context.Request.Url.AbsolutePath.IndexOf(ASPNETIdentityConfig.OAuth2AuthorizeEndpoint) != -1) { #region response_type @@ -423,31 +422,39 @@ private void OnPreSendRequestHeaders(object sender, EventArgs e) // - or [response_type=id_token token] // レスポンス内容を参照して書き換え(fragmentにid_tokenを追加) - string location = response.Headers["Location"]; + string location = response.Headers[OAuth2AndOIDCConst.HttpHeader_Location]; if (!string.IsNullOrEmpty(location) && location.IndexOf("#access_token=") != -1) { + string pattern = ""; + // ・正規表現でaccess_tokenを抜き出す。 - string pattern = "(\\#access_token=)(?.+?)(\\&)"; + pattern = "(\\#access_token=)(?.+?)(\\&)"; access_token = Regex.Match(location, pattern).Groups["accessToken"].Value; - // at_hashを付与 - id_token = OidcTokenEditor.ChangeToIdTokenFromAccessToken(access_token, "", HashClaimType.AtHash); + // ・正規表現でstateを抜き出す。 + pattern = "&state=(?.+)"; + state = Regex.Match(location, pattern).Groups["state"].Value; + + // at_hash と s_hashを付与 + id_token = IdToken.ChangeToIdTokenFromAccessToken( + access_token, "", state, HashClaimType.AtHash | HashClaimType.SHash, // ★ + ASPNETIdentityConfig.OAuth2JWT_pfx, ASPNETIdentityConfig.OAuth2JWTPassword); if (!string.IsNullOrEmpty(id_token)) { // responseにid_tokenとして、このJWTを追加する。 if (this.RewritedResponseTypeFrom_IdTokenToken) { - response.Headers["Location"] = location + "&id_token=" + id_token; + response.Headers[OAuth2AndOIDCConst.HttpHeader_Location] = location + "&id_token=" + id_token; } else if (this.RewritedResponseTypeFrom_IdToken) { // ココは未サポート状態なので、テストできていない。 location = location.Replace("access_token=" + access_token + "&", ""); location = location.Replace("&token_type=beara", ""); - response.Headers["Location"] = location + "&id_token=" + id_token; + response.Headers[OAuth2AndOIDCConst.HttpHeader_Location] = location + "&id_token=" + id_token; } } } @@ -473,7 +480,7 @@ private void OnPreSendRequestHeaders(object sender, EventArgs e) // ・本来は、 // "http(s)://redirect_uri値?code=code値&state=state値" // を期待していた。 - string location = response.Headers["Location"]; + string location = response.Headers[OAuth2AndOIDCConst.HttpHeader_Location]; string paramStrCode = "?code="; string paramStrState = "&state="; @@ -483,7 +490,7 @@ private void OnPreSendRequestHeaders(object sender, EventArgs e) || location.IndexOf(paramStrState) != -1 || location.IndexOf(paramStrRedirectUri) != -1) { - response.Headers.Remove("Location"); + response.Headers.Remove(OAuth2AndOIDCConst.HttpHeader_Location); // 以下は、"?code=XXX&state=YYY&" という並びが前提。 MatchCollection matches = StringChecker.Matches( @@ -493,14 +500,15 @@ private void OnPreSendRequestHeaders(object sender, EventArgs e) foreach (Match match in matches) { GroupCollection groups = match.Groups; - code = groups["code"].Value; - state = groups["state"].Value; + code = groups[OAuth2AndOIDCConst.code].Value; + state = groups[OAuth2AndOIDCConst.state].Value; } redirect_url = location.Substring(0, location.IndexOf('?')); // ★ Hybrid Flow対応なので、expを短縮してもイイ。 - expires_in = ulong.Parse(ASPNETIdentityConfig.OAuthAccessTokenExpireTimeSpanFromMinutes.TotalSeconds.ToString()); + expires_in = ulong.Parse( + ASPNETIdentityConfig.OAuth2AccessTokenExpireTimeSpanFromMinutes.TotalSeconds.ToString()); // Fragmentに組み込む string fragment = ""; @@ -510,9 +518,11 @@ private void OnPreSendRequestHeaders(object sender, EventArgs e) // id_tokenを取得 string access_token_payload = AuthorizationCodeProvider.GetInstance().GetAccessTokenPayload(code); - // c_hashを付与 - id_token = OidcTokenEditor.ChangeToIdTokenFromAccessToken( - OidcTokenEditor.ProtectFromPayload(access_token_payload, expires_in), code, HashClaimType.CHash); + // c_hash, s_hashを付与 + id_token = IdToken.ChangeToIdTokenFromAccessToken( + OidcTokenEditor.ProtectFromAccessTokenPayload(access_token_payload, expires_in), + code, state, HashClaimType.CHash | HashClaimType.SHash, + ASPNETIdentityConfig.OAuth2JWT_pfx, ASPNETIdentityConfig.OAuth2JWTPassword); fragment = "#id_token={0}&token_type=Bearer&code={1}&expires_in={2}&state={3}"; fragment = string.Format(fragment, new object[] { id_token, code, expires_in, state }); @@ -521,7 +531,7 @@ private void OnPreSendRequestHeaders(object sender, EventArgs e) { // access_tokenを取得 string access_token_payload = AuthorizationCodeProvider.GetInstance().GetAccessTokenPayload(code); - access_token = OidcTokenEditor.ProtectFromPayload(access_token_payload, expires_in); + access_token = OidcTokenEditor.ProtectFromAccessTokenPayload(access_token_payload, expires_in); fragment = "#access_token={0}&token_type=Bearer&code={1}&expires_in={2}&state={3}"; fragment = string.Format(fragment, new object[] { access_token, code, expires_in, state }); @@ -530,17 +540,19 @@ private void OnPreSendRequestHeaders(object sender, EventArgs e) { // id_token, access_tokenを取得 string access_token_payload = AuthorizationCodeProvider.GetInstance().GetAccessTokenPayload(code); - access_token = OidcTokenEditor.ProtectFromPayload(access_token_payload, expires_in); + access_token = OidcTokenEditor.ProtectFromAccessTokenPayload(access_token_payload, expires_in); - // at_hash, c_hashの両方を付与 - id_token = OidcTokenEditor.ChangeToIdTokenFromAccessToken(access_token, code, HashClaimType.Both); + // at_hash, c_hash, s_hashを付与 + id_token = IdToken.ChangeToIdTokenFromAccessToken(access_token, code, state, + HashClaimType.AtHash | HashClaimType.CHash | HashClaimType.SHash, + ASPNETIdentityConfig.OAuth2JWT_pfx, ASPNETIdentityConfig.OAuth2JWTPassword); fragment = "#access_token={0}&id_token={1}&token_type=Bearer&code={2}&expires_in={3}&state={4}"; fragment = string.Format(fragment, new object[] { access_token, id_token, code, expires_in, state }); } // Locationを追加(redirect_url + fragment)。 - response.Headers.Add("Location", redirect_url + fragment); + response.Headers.Add(OAuth2AndOIDCConst.HttpHeader_Location, redirect_url + fragment); } } } @@ -566,7 +578,7 @@ private void OnPreSendRequestHeaders(object sender, EventArgs e) // ・本来は、 // "http(s)://redirect_uri値?code=code値&state=state値" // を期待していた。 - string location = response.Headers["Location"]; + string location = response.Headers[OAuth2AndOIDCConst.HttpHeader_Location]; string paramStrCode = "?code="; string paramStrState = "&state="; @@ -578,7 +590,7 @@ private void OnPreSendRequestHeaders(object sender, EventArgs e) { // 302 Found ---> 200 OK response.StatusCode = 200; - response.Headers.Remove("Location"); + response.Headers.Remove(OAuth2AndOIDCConst.HttpHeader_Location); // 以下は、"?code=XXX&state=YYY&redirect_uri=ZZZ" という並びが前提。 MatchCollection matches = StringChecker.Matches( @@ -588,9 +600,9 @@ private void OnPreSendRequestHeaders(object sender, EventArgs e) foreach (Match match in matches) { GroupCollection groups = match.Groups; - code = groups["code"].Value; - state = groups["state"].Value; - redirect_url = CustomEncode.UrlDecode(groups["redirect_uri"].Value); + code = groups[OAuth2AndOIDCConst.code].Value; + state = groups[OAuth2AndOIDCConst.state].Value; + redirect_url = CustomEncode.UrlDecode(groups[OAuth2AndOIDCConst.redirect_uri].Value); } // form_postに必要な、HTTP response message body diff --git a/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ASPNETIdentity/StartupAuth.cs b/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ASPNETIdentity/StartupAuth.cs index 061afc15..65761d1b 100644 --- a/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ASPNETIdentity/StartupAuth.cs +++ b/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ASPNETIdentity/StartupAuth.cs @@ -42,6 +42,8 @@ using MultiPurposeAuthSite.Models.ASPNETIdentity.Entity; using MultiPurposeAuthSite.Models.ASPNETIdentity.TokenProviders; +using Touryo.Infrastructure.Framework.Authentication; + /// MultiPurposeAuthSite.Models.ASPNETIdentity namespace MultiPurposeAuthSite.Models.ASPNETIdentity { @@ -279,9 +281,9 @@ public static void Configure(IAppBuilder app) ClientSecret = ASPNETIdentityConfig.GoogleAuthenticationClientSecret }; // スコープを追加する。 - options.Scope.Add("openid"); - options.Scope.Add("profile"); - options.Scope.Add("email"); + options.Scope.Add(OAuth2AndOIDCConst.Scope_Openid); + options.Scope.Add(OAuth2AndOIDCConst.Scope_Profile); + options.Scope.Add(OAuth2AndOIDCConst.Scope_Email); // GoogleAuthenticationの有効化 app.UseGoogleAuthentication(options); @@ -312,7 +314,7 @@ public static void Configure(IAppBuilder app) } }; // スコープを追加する。 - options.Scope.Add("email"); + options.Scope.Add(OAuth2AndOIDCConst.Scope_Email); // FacebookAuthenticationの有効化 app.UseFacebookAuthentication(options); @@ -380,7 +382,7 @@ public static void Configure(IAppBuilder app) // c# - ASP.Net identity: Difference between UseOAuthBearerTokens and UseCookieAuthentication? - Stack Overflow // http://stackoverflow.com/questions/22121330/asp-net-identity-difference-between-useoauthbearertokens-and-usecookieauthentic - if (ASPNETIdentityConfig.EquipOAuthServer) + if (ASPNETIdentityConfig.EquipOAuth2Server) { // OAuth Bearer Tokenを使用可能に設定する。 // UseOAuthAuthorizationServerとUseOAuthBearerTokensの違いが不明だが、 @@ -468,19 +470,19 @@ public static void Configure(IAppBuilder app) //AccessTokenFormat = new AccessTokenFormatJwt(), // ・AccessTokenExpireTimeSpan(OAuth Access Token の 有効期限 - AccessTokenExpireTimeSpan = ASPNETIdentityConfig.OAuthAccessTokenExpireTimeSpanFromMinutes, // System.TimeSpan.FromSeconds(10), // Debug時 + AccessTokenExpireTimeSpan = ASPNETIdentityConfig.OAuth2AccessTokenExpireTimeSpanFromMinutes, // System.TimeSpan.FromSeconds(10), // Debug時 // ・AllowInsecureHttp // 認証して、Token要求が http URI アドレスに届くことを許可し、 // 受信する redirect_uri 承認要求パラメータに http URI アドレスを設定する場合は true。 - AllowInsecureHttp = ASPNETIdentityConfig.AllowOAuthInsecureHttpEndpoints, + AllowInsecureHttp = ASPNETIdentityConfig.AllowOAuth2InsecureHttpEndpoints, #endregion #region Implicitグラント種別を除く全てのグラント種別の共通設定 // ・OAuth Bearer Token の Token Endpoint - TokenEndpointPath = new PathString(ASPNETIdentityConfig.OAuthBearerTokenEndpoint), + TokenEndpointPath = new PathString(ASPNETIdentityConfig.OAuth2BearerTokenEndpoint), #endregion @@ -488,11 +490,11 @@ public static void Configure(IAppBuilder app) // ・AuthorizeEndpointPath // OAuth の Authorize Endpoint - AuthorizeEndpointPath = new PathString(ASPNETIdentityConfig.OAuthAuthorizeEndpoint), + AuthorizeEndpointPath = new PathString(ASPNETIdentityConfig.OAuth2AuthorizeEndpoint), // ・ApplicationCanDisplayErrors // AuthorizeEndpointPath上でエラー メッセージを表示できるようにする。 - ApplicationCanDisplayErrors = ASPNETIdentityConfig.OAuthAuthorizeEndpointCanDisplayErrors, + ApplicationCanDisplayErrors = ASPNETIdentityConfig.OAuth2AuthorizeEndpointCanDisplayErrors, #endregion diff --git a/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ASPNETIdentity/TokenProviders/AccessTokenFormatJwt.cs b/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ASPNETIdentity/TokenProviders/AccessTokenFormatJwt.cs index f044a4e9..6dfd621a 100644 --- a/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ASPNETIdentity/TokenProviders/AccessTokenFormatJwt.cs +++ b/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ASPNETIdentity/TokenProviders/AccessTokenFormatJwt.cs @@ -33,12 +33,12 @@ using System; using System.Web; -using System.Security.Claims; +using System.Linq; using System.Collections.Generic; +using System.Security.Claims; using System.Security.Cryptography.X509Certificates; using Microsoft.Owin.Security; -using Microsoft.Owin.Security.OAuth; using Microsoft.AspNet.Identity; using Microsoft.AspNet.Identity.Owin; @@ -49,6 +49,8 @@ using MultiPurposeAuthSite.Models.ASPNETIdentity.Entity; using MultiPurposeAuthSite.Models.ASPNETIdentity.OAuth2Extension; +using Touryo.Infrastructure.Framework.Authentication; +using Touryo.Infrastructure.Public.IO; using Touryo.Infrastructure.Public.Str; using Touryo.Infrastructure.Public.Security; @@ -66,7 +68,7 @@ public AccessTokenFormatJwt() { } public string Protect(AuthenticationTicket ticket) { string json = ""; - string jwt = ""; + //string jws = ""; // チェック if (ticket == null) @@ -98,19 +100,19 @@ ApplicationUserManager userManager foreach (Claim c in ticket.Identity.Claims) { - if (c.Type == ASPNETIdentityConst.Claim_Issuer) + if (c.Type == OAuth2AndOIDCConst.Claim_Issuer) { - authTokenClaimSet.Add("iss", c.Value); + authTokenClaimSet.Add(OAuth2AndOIDCConst.iss, c.Value); } - else if (c.Type == ASPNETIdentityConst.Claim_Audience) + else if (c.Type == OAuth2AndOIDCConst.Claim_Audience) { - authTokenClaimSet.Add("aud", c.Value); + authTokenClaimSet.Add(OAuth2AndOIDCConst.aud, c.Value); } - else if (c.Type == ASPNETIdentityConst.Claim_Nonce) + else if (c.Type == OAuth2AndOIDCConst.Claim_Nonce) { - authTokenClaimSet.Add("nonce", c.Value); + authTokenClaimSet.Add(OAuth2AndOIDCConst.nonce, c.Value); } - else if (c.Type == ASPNETIdentityConst.Claim_Scope) + else if (c.Type == OAuth2AndOIDCConst.Claim_Scopes) { scopes.Add(c.Value); } @@ -123,21 +125,21 @@ ApplicationUserManager userManager if (ticket.Identity.Name == null) { // Client認証の場合、aud(client_id)に対応するClient名称 - authTokenClaimSet.Add("sub", - OAuth2Helper.GetInstance().GetClientName((string)authTokenClaimSet["aud"])); + authTokenClaimSet.Add(OAuth2AndOIDCConst.sub, + OAuth2Helper.GetInstance().GetClientName((string)authTokenClaimSet[OAuth2AndOIDCConst.aud])); } else { // Resource Owner認証の場合、Resource Ownerの名称 - authTokenClaimSet.Add("sub", ticket.Identity.Name); + authTokenClaimSet.Add(OAuth2AndOIDCConst.sub, ticket.Identity.Name); } - authTokenClaimSet.Add("exp", ticket.Properties.ExpiresUtc.Value.ToUnixTimeSeconds().ToString()); - authTokenClaimSet.Add("nbf", DateTimeOffset.Now.ToUnixTimeSeconds().ToString()); - authTokenClaimSet.Add("iat", ticket.Properties.IssuedUtc.Value.ToUnixTimeSeconds().ToString()); - authTokenClaimSet.Add("jti", Guid.NewGuid().ToString("N")); + authTokenClaimSet.Add(OAuth2AndOIDCConst.exp, ticket.Properties.ExpiresUtc.Value.ToUnixTimeSeconds().ToString()); + authTokenClaimSet.Add(OAuth2AndOIDCConst.nbf, DateTimeOffset.Now.ToUnixTimeSeconds().ToString()); + authTokenClaimSet.Add(OAuth2AndOIDCConst.iat, ticket.Properties.IssuedUtc.Value.ToUnixTimeSeconds().ToString()); + authTokenClaimSet.Add(OAuth2AndOIDCConst.jti, Guid.NewGuid().ToString("N")); - authTokenClaimSet.Add("scopes", scopes); + authTokenClaimSet.Add(OAuth2AndOIDCConst.scopes, scopes); // scope値によって、返す値を変更する。 foreach (string scope in scopes) @@ -149,18 +151,18 @@ ApplicationUserManager userManager { #region OpenID Connect - case ASPNETIdentityConst.Scope_Profile: + case OAuth2AndOIDCConst.Scope_Profile: // ・・・ break; - case ASPNETIdentityConst.Scope_Email: - authTokenClaimSet.Add("email", user.Email); - authTokenClaimSet.Add("email_verified", user.EmailConfirmed.ToString()); + case OAuth2AndOIDCConst.Scope_Email: + authTokenClaimSet.Add(OAuth2AndOIDCConst.Scope_Email, user.Email); + authTokenClaimSet.Add(OAuth2AndOIDCConst.email_verified, user.EmailConfirmed.ToString()); break; - case ASPNETIdentityConst.Scope_Phone: - authTokenClaimSet.Add("phone_number", user.PhoneNumber); - authTokenClaimSet.Add("phone_number_verified", user.PhoneNumberConfirmed.ToString()); + case OAuth2AndOIDCConst.Scope_Phone: + authTokenClaimSet.Add(OAuth2AndOIDCConst.phone_number, user.PhoneNumber); + authTokenClaimSet.Add(OAuth2AndOIDCConst.phone_number_verified, user.PhoneNumberConfirmed.ToString()); break; - case ASPNETIdentityConst.Scope_Address: + case OAuth2AndOIDCConst.Scope_Address: // ・・・ break; @@ -168,12 +170,12 @@ ApplicationUserManager userManager #region Else - case ASPNETIdentityConst.Scope_Userid: - authTokenClaimSet.Add(ASPNETIdentityConst.Scope_Userid, user.Id); + case OAuth2AndOIDCConst.Scope_UserID: + authTokenClaimSet.Add(OAuth2AndOIDCConst.Scope_UserID, user.Id); break; - case ASPNETIdentityConst.Scope_Roles: + case OAuth2AndOIDCConst.Scope_Roles: authTokenClaimSet.Add( - ASPNETIdentityConst.Scope_Roles, + OAuth2AndOIDCConst.Scope_Roles, userManager.GetRolesAsync(user.Id).Result); break; @@ -190,28 +192,38 @@ ApplicationUserManager userManager #endregion - #region JWT化 + #region JWS化 - JWT_RS256 jwtRS256 = null; + JWS_RS256_X509 jwsRS256 = null; - // 署名 - jwtRS256 = new JWT_RS256(ASPNETIdentityConfig.OAuthJWT_pfx, ASPNETIdentityConfig.OAuthJWTPassword, + // JWT_RS256_X509 + jwsRS256 = new JWS_RS256_X509(ASPNETIdentityConfig.OAuth2JWT_pfx, ASPNETIdentityConfig.OAuth2JWTPassword, X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet); - jwt = jwtRS256.Create(json); + // JWSHeaderのセット + // kid : https://openid-foundation-japan.github.io/rfc7638.ja.html#Example + Dictionary jwk = + JsonConvert.DeserializeObject>( + RS256_KeyConverter.X509PfxToJwkPublicKey(ASPNETIdentityConfig.OAuth2JWT_pfx, ASPNETIdentityConfig.OAuth2JWTPassword)); - // 検証 - jwtRS256 = new JWT_RS256(ASPNETIdentityConfig.OAuthJWT_cer, ASPNETIdentityConfig.OAuthJWTPassword, - X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet); + jwsRS256.JWSHeader.kid = jwk[JwtConst.kid]; + jwsRS256.JWSHeader.jku = ASPNETIdentityConfig.OAuth2AuthorizationServerEndpointsRootURI + OAuth2AndOIDCParams.JwkSetUri; - if (jwtRS256.Verify(jwt)) - { - return jwt; // 検証できた。 - } - else - { - return ""; // 検証できなかった。 - } + // 署名 + return jwsRS256.Create(json); + + //// 検証 + //jwsRS256 = new JWS_RS256_X509(OAuth2AndOIDCParams.RS256Cer, ASPNETIdentityConfig.OAuth2JWTPassword, + // X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet); + + //if (jwsRS256.Verify(jws)) + //{ + // return jws; // 検証できた。 + //} + //else + //{ + // return ""; // 検証できなかった。 + //} #endregion } @@ -228,8 +240,39 @@ public AuthenticationTicket Unprotect(string jwt) } // 検証 - JWT_RS256 jwtRS256 = new JWT_RS256(ASPNETIdentityConfig.OAuthJWT_cer, ASPNETIdentityConfig.OAuthJWTPassword); - if (jwtRS256.Verify(jwt)) + JWS_RS256 jwsRS256 = null; + + // 証明書を使用するか、Jwkを使用するか判定 + Dictionary header = JsonConvert.DeserializeObject>( + CustomEncode.ByteToString(CustomEncode.FromBase64UrlString(jwt.Split('.')[0]),CustomEncode.UTF_8)); + + if (header.Keys.Any(s => s == JwtConst.kid)) + { + if (string.IsNullOrEmpty(header[JwtConst.kid])) + { + // 証明書を使用 + jwsRS256 = new JWS_RS256_X509(OAuth2AndOIDCParams.RS256Cer, ""); + } + else + { + JwkSet jwkSetObject = JwkSet.LoadJwkSet(OAuth2AndOIDCParams.JwkSetFilePath); + JObject jwkObject = JwkSet.GetJwkObject(jwkSetObject, header[JwtConst.kid]); + + if (jwkObject == null) + { + // 証明書を使用 + jwsRS256 = new JWS_RS256_X509(OAuth2AndOIDCParams.RS256Cer, ""); + } + else + { + // Jwkを使用 + jwsRS256 = new JWS_RS256_Param( + RS256_KeyConverter.JwkToProvider(jwkObject).ExportParameters(false)); + } + } + } + + if (jwsRS256.Verify(jwt)) { // 検証できた。 @@ -245,20 +288,20 @@ public AuthenticationTicket Unprotect(string jwt) // ★ "exp": JWT の有効期限(Unix時間) // ☆ "jti": JWT のID(OAuth Token Revocation) - DateTime? datetime = OAuth2RevocationProvider.GetInstance().Get((string)authTokenClaimSet["jti"]); + DateTime? datetime = OAuth2RevocationProvider.GetInstance().Get((string)authTokenClaimSet[OAuth2AndOIDCConst.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()) + if ((string)authTokenClaimSet[OAuth2AndOIDCConst.iss] == ASPNETIdentityConfig.OAuth2IssuerId + && OAuth2Helper.GetInstance().GetClientSecret((string)authTokenClaimSet[OAuth2AndOIDCConst.aud]) != null + && long.Parse((string)authTokenClaimSet[OAuth2AndOIDCConst.exp]) >= DateTimeOffset.Now.ToUnixTimeSeconds()) { // authToken.subの検証 // ApplicationUser を取得する。 ApplicationUserManager userManager = HttpContext.Current.GetOwinContext().GetUserManager(); - ApplicationUser user = userManager.FindByName((string)authTokenClaimSet["sub"]); // 同期版でOK。 + ApplicationUser user = userManager.FindByName((string)authTokenClaimSet[OAuth2AndOIDCConst.sub]); // 同期版でOK。 if (user != null) { @@ -269,24 +312,24 @@ ApplicationUserManager userManager // aud、scopes、nonceなどのClaimを追加する。 List scopes = new List(); - foreach (string s in (JArray)authTokenClaimSet["scopes"]) + foreach (string s in (JArray)authTokenClaimSet[OAuth2AndOIDCConst.scopes]) { scopes.Add(s); } OAuth2Helper.AddClaim(identity, - (string)authTokenClaimSet["aud"], "", scopes, (string)authTokenClaimSet["nonce"]); + (string)authTokenClaimSet[OAuth2AndOIDCConst.aud], "", scopes, (string)authTokenClaimSet[OAuth2AndOIDCConst.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"])); + identity.AddClaim(new Claim(OAuth2AndOIDCConst.Claim_ExpirationTime, (string)authTokenClaimSet[OAuth2AndOIDCConst.exp])); + identity.AddClaim(new Claim(OAuth2AndOIDCConst.Claim_NotBefore, (string)authTokenClaimSet[OAuth2AndOIDCConst.nbf])); + identity.AddClaim(new Claim(OAuth2AndOIDCConst.Claim_IssuedAt, (string)authTokenClaimSet[OAuth2AndOIDCConst.iat])); + identity.AddClaim(new Claim(OAuth2AndOIDCConst.Claim_JwtId, (string)authTokenClaimSet[OAuth2AndOIDCConst.jti])); // AuthenticationPropertiesの生成 AuthenticationProperties prop = new AuthenticationProperties(); - prop.IssuedUtc = DateTimeOffset.FromUnixTimeSeconds(long.Parse((string)authTokenClaimSet["iat"])); - prop.ExpiresUtc = DateTimeOffset.FromUnixTimeSeconds(long.Parse((string)authTokenClaimSet["exp"])); + prop.IssuedUtc = DateTimeOffset.FromUnixTimeSeconds(long.Parse((string)authTokenClaimSet[OAuth2AndOIDCConst.iat])); + prop.ExpiresUtc = DateTimeOffset.FromUnixTimeSeconds(long.Parse((string)authTokenClaimSet[OAuth2AndOIDCConst.exp])); AuthenticationTicket auth = new AuthenticationTicket(identity, prop); @@ -299,34 +342,34 @@ ApplicationUserManager userManager // ClaimとStoreのAudience(aud)に対応するSubject(sub)が一致するかを確認し、一致する場合のみ、認証する。 // ※ でないと、UserStoreから削除されたUser Accountが、Client Accountに化けることになる。 - if ((string)authTokenClaimSet["sub"] == OAuth2Helper.GetInstance().GetClientName((string)authTokenClaimSet["aud"])) + if ((string)authTokenClaimSet[OAuth2AndOIDCConst.sub] == OAuth2Helper.GetInstance().GetClientName((string)authTokenClaimSet[OAuth2AndOIDCConst.aud])) { // ClaimsIdentityを生成し、 ClaimsIdentity identity = new ClaimsIdentity(DefaultAuthenticationTypes.ExternalBearer); // sub(client_idに対応するclient_name)Claimを設定する。 - identity.AddClaim(new Claim(ClaimTypes.Name, (string)authTokenClaimSet["sub"])); + identity.AddClaim(new Claim(ClaimTypes.Name, (string)authTokenClaimSet[OAuth2AndOIDCConst.sub])); // aud、scopes、nonceなどのClaimを追加する。 List scopes = new List(); - foreach (string s in (JArray)authTokenClaimSet["scopes"]) + foreach (string s in (JArray)authTokenClaimSet[OAuth2AndOIDCConst.scopes]) { scopes.Add(s); } OAuth2Helper.AddClaim(identity, - (string)authTokenClaimSet["aud"], "", scopes, (string)authTokenClaimSet["nonce"]); + (string)authTokenClaimSet[OAuth2AndOIDCConst.aud], "", scopes, (string)authTokenClaimSet[OAuth2AndOIDCConst.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"])); + identity.AddClaim(new Claim(OAuth2AndOIDCConst.Claim_ExpirationTime, (string)authTokenClaimSet[OAuth2AndOIDCConst.exp])); + identity.AddClaim(new Claim(OAuth2AndOIDCConst.Claim_NotBefore, (string)authTokenClaimSet[OAuth2AndOIDCConst.nbf])); + identity.AddClaim(new Claim(OAuth2AndOIDCConst.Claim_IssuedAt, (string)authTokenClaimSet[OAuth2AndOIDCConst.iat])); + identity.AddClaim(new Claim(OAuth2AndOIDCConst.Claim_JwtId, (string)authTokenClaimSet[OAuth2AndOIDCConst.jti])); // AuthenticationPropertiesの生成 AuthenticationProperties prop = new AuthenticationProperties(); - prop.IssuedUtc = DateTimeOffset.FromUnixTimeSeconds(long.Parse((string)authTokenClaimSet["iat"])); - prop.ExpiresUtc = DateTimeOffset.FromUnixTimeSeconds(long.Parse((string)authTokenClaimSet["exp"])); + prop.IssuedUtc = DateTimeOffset.FromUnixTimeSeconds(long.Parse((string)authTokenClaimSet[OAuth2AndOIDCConst.iat])); + prop.ExpiresUtc = DateTimeOffset.FromUnixTimeSeconds(long.Parse((string)authTokenClaimSet[OAuth2AndOIDCConst.exp])); AuthenticationTicket auth = new AuthenticationTicket(identity, prop); diff --git a/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ASPNETIdentity/TokenProviders/ApplicationOAuthBearerTokenProvider.cs b/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ASPNETIdentity/TokenProviders/ApplicationOAuthBearerTokenProvider.cs index ed61467d..a699fa24 100644 --- a/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ASPNETIdentity/TokenProviders/ApplicationOAuthBearerTokenProvider.cs +++ b/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ASPNETIdentity/TokenProviders/ApplicationOAuthBearerTokenProvider.cs @@ -37,15 +37,24 @@ using MultiPurposeAuthSite.Models.ASPNETIdentity.OAuth2Extension; using System; -using System.Web; +using System.Collections.Generic; using System.Threading.Tasks; using System.Security.Claims; +using System.Web; +using System.Net.Http; + using Microsoft.Owin.Security; using Microsoft.Owin.Security.OAuth; using Microsoft.AspNet.Identity; using Microsoft.AspNet.Identity.Owin; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +using Touryo.Infrastructure.Framework.Authentication; +using Touryo.Infrastructure.Public.Str; + /// MultiPurposeAuthSite.Models.ASPNETIdentity.TokenProviders namespace MultiPurposeAuthSite.Models.ASPNETIdentity.TokenProviders { @@ -93,21 +102,21 @@ public override Task ValidateClientRedirectUri(OAuthValidateClientRedirectUriCon // OIDC Implicit, Hybridの場合、書き換え if (ASPNETIdentityConfig.EnableOpenIDConnect) { - if (response_type.ToLower() == ASPNETIdentityConst.OidcImplicit1_ResponseType - || response_type.ToLower() == ASPNETIdentityConst.OidcImplicit2_ResponseType - || response_type.ToLower() == ASPNETIdentityConst.OidcHybrid2_IdToken_ResponseType - || response_type.ToLower() == ASPNETIdentityConst.OidcHybrid2_Token_ResponseType - || response_type.ToLower() == ASPNETIdentityConst.OidcHybrid3_ResponseType) + if (response_type.ToLower() == OAuth2AndOIDCConst.OidcImplicit1_ResponseType + || response_type.ToLower() == OAuth2AndOIDCConst.OidcImplicit2_ResponseType + || response_type.ToLower() == OAuth2AndOIDCConst.OidcHybrid2_IdToken_ResponseType + || response_type.ToLower() == OAuth2AndOIDCConst.OidcHybrid2_Token_ResponseType + || response_type.ToLower() == OAuth2AndOIDCConst.OidcHybrid3_ResponseType) { // OIDC Implicit, Hybridの場合、書き換え // Authorization Code Flowの場合は、codeなので書き換え不要。 // ※ この変数は、使用するredirect_uriを決定するだめダケに利用される。 - response_type = ASPNETIdentityConst.ImplicitResponseType; + response_type = OAuth2AndOIDCConst.ImplicitResponseType; // OIDC Implicit Flow、Hybrid Flowのパラメタチェック // nonceパラメタ 必須 - string nonce = context.Request.Query.Get("nonce"); + string nonce = context.Request.Query.Get(OAuth2AndOIDCConst.nonce); if (string.IsNullOrEmpty(nonce)) { //throw new NotSupportedException("there was no nonce in query."); @@ -118,8 +127,8 @@ public override Task ValidateClientRedirectUri(OAuthValidateClientRedirectUriCon } // scopeパラメタ 必須 - string scope = context.Request.Query.Get("scope"); - if (scope.IndexOf("openid") == -1) + string scope = context.Request.Query.Get(OAuth2AndOIDCConst.scope); + if (scope.IndexOf(OAuth2AndOIDCConst.Scope_Openid) == -1) { //throw new NotSupportedException("there was no openid in scope of query."); context.SetError( @@ -132,7 +141,7 @@ public override Task ValidateClientRedirectUri(OAuthValidateClientRedirectUriCon if (!string.IsNullOrEmpty(response_type)) { - if (response_type.ToLower() == ASPNETIdentityConst.AuthorizationCodeResponseType) + if (response_type.ToLower() == OAuth2AndOIDCConst.AuthorizationCodeResponseType) { if (!ASPNETIdentityConfig.EnableAuthorizationCodeGrantType) { @@ -143,7 +152,7 @@ public override Task ValidateClientRedirectUri(OAuthValidateClientRedirectUriCon return Task.FromResult(0); } } - else if (response_type.ToLower() == ASPNETIdentityConst.ImplicitResponseType) + else if (response_type.ToLower() == OAuth2AndOIDCConst.ImplicitResponseType) { if (!ASPNETIdentityConfig.EnableImplicitGrantType) { @@ -177,15 +186,15 @@ public override Task ValidateClientRedirectUri(OAuthValidateClientRedirectUriCon { // Authorization Codeグラント種別のテスト用のセルフRedirectエンドポイント context.Validated( - ASPNETIdentityConfig.OAuthClientEndpointsRootURI - + ASPNETIdentityConfig.OAuthAuthorizationCodeGrantClient_Account); + ASPNETIdentityConfig.OAuth2ClientEndpointsRootURI + + ASPNETIdentityConfig.OAuth2AuthorizationCodeGrantClient_Account); } else if (redirect_uri.ToLower() == "test_self_token") { // Implicitグラント種別のテスト用のセルフRedirectエンドポイント context.Validated( - ASPNETIdentityConfig.OAuthClientEndpointsRootURI - + ASPNETIdentityConfig.OAuthImplicitGrantClient_Account); + ASPNETIdentityConfig.OAuth2ClientEndpointsRootURI + + ASPNETIdentityConfig.OAuth2ImplicitGrantClient_Account); } else if (redirect_uri.ToLower() == "id_federation_code") { @@ -210,7 +219,7 @@ public override Task ValidateClientRedirectUri(OAuthValidateClientRedirectUriCon // 指定されたredirect_uriを使用する場合は、チェックが必要になる。 if ( // self_code : Authorization Codeグラント種別 - redirect_uri == (ASPNETIdentityConfig.OAuthClientEndpointsRootURI + ASPNETIdentityConfig.OAuthAuthorizationCodeGrantClient_Manage) + redirect_uri == (ASPNETIdentityConfig.OAuth2ClientEndpointsRootURI + ASPNETIdentityConfig.OAuth2AuthorizationCodeGrantClient_Manage) ) { // 不特定多数のクライアント識別子に許可されたredirect_uri @@ -269,18 +278,19 @@ public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticat #region クライアント認証を行なう。 - if (string.IsNullOrEmpty(context.Parameters["grant_type"])) + if (string.IsNullOrEmpty(context.Parameters[OAuth2AndOIDCConst.grant_type])) { // 指定なし。 // 検証未完 } - else if (context.Parameters["grant_type"].ToLower() == ASPNETIdentityConst.AuthorizationCodeGrantType) + else if (context.Parameters[OAuth2AndOIDCConst.grant_type].ToLower() == OAuth2AndOIDCConst.AuthorizationCodeGrantType) { #region Authorization Codeグラント種別 // "client_id" および "client_secret"を基本認証の認証ヘッダから取得 if (context.TryGetBasicCredentials(out clientId, out clientSecret)) { + // 通常のクライアント認証 if (!(string.IsNullOrEmpty(clientId) && string.IsNullOrEmpty(clientSecret))) { // *.config or OAuth2Dataテーブルを参照してクライアント認証を行なう。 @@ -291,10 +301,49 @@ public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticat } } } + else + { + // その他のクライアント認証の可能性 + string assertion = context.Parameters.Get(OAuth2AndOIDCConst.assertion); + if (!string.IsNullOrEmpty(assertion)) + { + // JWT client assertion + Dictionary dic = JsonConvert.DeserializeObject>( + CustomEncode.ByteToString(CustomEncode.FromBase64UrlString( + assertion.Split('.')[1]), CustomEncode.us_ascii)); + + string pubKey = OAuth2Helper.GetInstance().GetJwtAssertionPublickey(dic[OAuth2AndOIDCConst.iss]); + pubKey = CustomEncode.ByteToString(CustomEncode.FromBase64String(pubKey), CustomEncode.us_ascii); + + if (!string.IsNullOrEmpty(pubKey)) + { + string iss = ""; + string aud = ""; + string scopes = ""; + JObject jobj = null; + + if (JwtAssertion.VerifyJwtBearerTokenFlowAssertion( + assertion, out iss, out aud, out scopes, out jobj, pubKey)) + { + // aud 検証 + if (aud == ASPNETIdentityConfig.OAuth2AuthorizationServerEndpointsRootURI + + ASPNETIdentityConfig.OAuth2BearerTokenEndpoint) + { + // 検証完了 + context.Validated(iss); + } + } + } + } + else + { + // クライアント認証なしエラー + } + } #endregion } - else if (context.Parameters["grant_type"].ToLower() == ASPNETIdentityConst.ResourceOwnerPasswordCredentialsGrantType) + else if (context.Parameters[OAuth2AndOIDCConst.grant_type].ToLower() == OAuth2AndOIDCConst.ResourceOwnerPasswordCredentialsGrantType) { #region Resource Owner Password Credentialsグラント種別 @@ -321,7 +370,7 @@ public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticat #endregion } - else if (context.Parameters["grant_type"].ToLower() == ASPNETIdentityConst.ClientCredentialsGrantType) + else if (context.Parameters[OAuth2AndOIDCConst.grant_type].ToLower() == OAuth2AndOIDCConst.ClientCredentialsGrantType) { #region Client Credentialsグラント種別 @@ -341,7 +390,7 @@ public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticat #endregion } - else if (context.Parameters["grant_type"].ToLower() == ASPNETIdentityConst.RefreshTokenGrantType) + else if (context.Parameters[OAuth2AndOIDCConst.grant_type].ToLower() == OAuth2AndOIDCConst.RefreshTokenGrantType) { #region RefreshToken @@ -393,7 +442,7 @@ public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticat /// public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context) { - if (!ASPNETIdentityConfig.EnableResourceOwnerCredentialsGrantType) + if (!ASPNETIdentityConfig.EnableResourceOwnerPasswordCredentialsGrantType) { throw new NotSupportedException(Resources.ApplicationOAuthBearerTokenProvider.EnableResourceOwnerCredentialsGrantType); } diff --git a/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ASPNETIdentity/TokenProviders/AuthorizationCodeProvider.cs b/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ASPNETIdentity/TokenProviders/AuthorizationCodeProvider.cs index 0beaf1cf..3378abad 100644 --- a/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ASPNETIdentity/TokenProviders/AuthorizationCodeProvider.cs +++ b/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ASPNETIdentity/TokenProviders/AuthorizationCodeProvider.cs @@ -54,8 +54,7 @@ using Dapper; using Newtonsoft.Json; -using Touryo.Infrastructure.Public.IO; -using Touryo.Infrastructure.Public.Str; +using Touryo.Infrastructure.Framework.Authentication; namespace MultiPurposeAuthSite.Models.ASPNETIdentity.TokenProviders { @@ -116,12 +115,12 @@ private void CreateAuthenticationCode(AuthenticationTokenCreateContext context) // 有効期限が無効なtokenのペイロードだけ作成 AccessTokenFormatJwt accessTokenFormatJwt = new AccessTokenFormatJwt(); - string access_token_payload = OidcTokenEditor.CreateAccessTokenPayload(context.Ticket); + string access_token_payload = OidcTokenEditor.CreateAccessTokenPayloadFromAuthenticationTicket(context.Ticket); temp.Add("access_token_payload", access_token_payload); // OAuth PKCE 対応 - temp.Add("code_challenge", queryString["code_challenge"]); - temp.Add("code_challenge_method", queryString["code_challenge_method"]); + temp.Add(OAuth2AndOIDCConst.code_challenge, queryString[OAuth2AndOIDCConst.code_challenge]); + temp.Add(OAuth2AndOIDCConst.code_challenge_method, queryString[OAuth2AndOIDCConst.code_challenge_method]); // Hybrid Flow対応 // OAuthAuthorizationServerHandler経由での呼び出しができず、 @@ -296,7 +295,7 @@ private string VerifyCodeVerifier(string value, string code_verifier) if (!isPKCE) { // 通常のアクセストークン・リクエスト - if (string.IsNullOrEmpty(temp["code_challenge"])) + if (string.IsNullOrEmpty(temp[OAuth2AndOIDCConst.code_challenge])) { // Authorization Codeのcode return temp["ticket"]; @@ -310,12 +309,12 @@ private string VerifyCodeVerifier(string value, string code_verifier) else { // OAuth PKCEのアクセストークン・リクエスト - if (!string.IsNullOrEmpty(temp["code_challenge"]) && !string.IsNullOrEmpty(code_verifier)) + if (!string.IsNullOrEmpty(temp[OAuth2AndOIDCConst.code_challenge]) && !string.IsNullOrEmpty(code_verifier)) { - if (temp["code_challenge_method"].ToLower() == "plain") + if (temp[OAuth2AndOIDCConst.code_challenge_method].ToLower() == OAuth2AndOIDCConst.PKCE_plain) { // plain - if (temp["code_challenge"] == code_verifier) + if (temp[OAuth2AndOIDCConst.code_challenge] == code_verifier) { // 検証成功 return temp["ticket"]; @@ -325,10 +324,10 @@ private string VerifyCodeVerifier(string value, string code_verifier) // 検証失敗 } } - else if (temp["code_challenge_method"].ToLower() == "s256") + else if (temp[OAuth2AndOIDCConst.code_challenge_method].ToUpper() == OAuth2AndOIDCConst.PKCE_S256) { - // s256 - if (temp["code_challenge"] == OAuth2Helper.PKCE_S256_CodeChallengeMethod(code_verifier)) + // S256 + if (temp[OAuth2AndOIDCConst.code_challenge] == OAuth2AndOIDCClient.PKCE_S256_CodeChallengeMethod(code_verifier)) { // 検証成功 return temp["ticket"]; diff --git a/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ASPNETIdentity/TokenProviders/RefreshTokenProvider.cs b/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ASPNETIdentity/TokenProviders/RefreshTokenProvider.cs index 33ff5b56..17abcf91 100644 --- a/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ASPNETIdentity/TokenProviders/RefreshTokenProvider.cs +++ b/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ASPNETIdentity/TokenProviders/RefreshTokenProvider.cs @@ -107,7 +107,7 @@ private void CreateRefreshToken(AuthenticationTokenCreateContext context) { // IssuedUtcとExpiredUtcという有効期限プロパティをAuthenticationTicketに追加 IssuedUtc = context.Ticket.Properties.IssuedUtc, - ExpiresUtc = DateTime.UtcNow.Add(ASPNETIdentityConfig.OAuthRefreshTokenExpireTimeSpanFromDays) // System.TimeSpan.FromSeconds(20)) // Debug時 + ExpiresUtc = DateTime.UtcNow.Add(ASPNETIdentityConfig.OAuth2RefreshTokenExpireTimeSpanFromDays) // System.TimeSpan.FromSeconds(20)) // Debug時 }; // AuthenticationTicket.IdentityのClaimsIdentity値を含む有効期限付きの新しいAuthenticationTicketを作成する。 diff --git a/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ASPNETIdentity/Util/CustomizedConfirmationProvider.cs b/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ASPNETIdentity/Util/CustomizedConfirmationProvider.cs index e3ed0872..765fff77 100644 --- a/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ASPNETIdentity/Util/CustomizedConfirmationProvider.cs +++ b/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ASPNETIdentity/Util/CustomizedConfirmationProvider.cs @@ -31,6 +31,8 @@ //* 2017/06/07 西野 大介 新規 //********************************************************************************** +using MultiPurposeAuthSite.Models.Util; + using System; using System.Data; using System.Collections.Generic; @@ -39,17 +41,17 @@ using Dapper; using Newtonsoft.Json; -using MultiPurposeAuthSite.Models.Util; +using Touryo.Infrastructure.Framework.Authentication; namespace MultiPurposeAuthSite.Models.ASPNETIdentity.Util { /// CustomizedConfirmationData public class CustomizedConfirmationJson { - [JsonProperty(PropertyName = "code")] + [JsonProperty(PropertyName = OAuth2AndOIDCConst.code)] public string Code { get; set; } - [JsonProperty(PropertyName = "email")] + [JsonProperty(PropertyName = OAuth2AndOIDCConst.Scope_Email)] public string Email { get; set; } } diff --git a/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/Util/WebAPIHelper.cs b/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/Util/WebAPIHelper.cs index 2476b619..a2f059a5 100644 --- a/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/Util/WebAPIHelper.cs +++ b/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/Util/WebAPIHelper.cs @@ -47,6 +47,7 @@ using Newtonsoft.Json; using Newtonsoft.Json.Linq; +using Touryo.Infrastructure.Framework.Authentication; using Touryo.Infrastructure.Public.Str; using Touryo.Infrastructure.Public.Util; @@ -245,7 +246,7 @@ public async Task GetTwitterAccountInfo( }; // HttpRequestMessage (Headers) - httpRequestMessage.Headers.Add("Authorization", authHeader); + httpRequestMessage.Headers.Add(OAuth2AndOIDCConst.HttpHeader_Authorization, authHeader); //httpRequestMessage.Headers.Authorization = new AuthenticationHeaderValue("OAuth", authHeader); //httpRequestMessage.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); @@ -259,7 +260,7 @@ public async Task GetTwitterAccountInfo( //ServicePointManager.Expect100Continue = false; //HttpWebRequest request = (HttpWebRequest)WebRequest.Create(resource_url); //request.Method = "GET"; - //request.Headers.Add("Authorization", authHeader); + //request.Headers.Add(OAuth2AndOIDCConst.HttpHeader_Authorization, authHeader); //WebResponse response = request.GetResponse(); //return JsonConvert.DeserializeObject>( // new StreamReader(response.GetResponseStream()).ReadToEnd()); @@ -307,14 +308,15 @@ public async Task CreateaOnlinePaymentCustomerAsync(string email, strin // HttpRequestMessage (Headers) httpRequestMessage.Headers.Authorization = new AuthenticationHeaderValue( - "Basic", CustomEncode.ToBase64String(CustomEncode.StringToByte(secretKey, CustomEncode.us_ascii))); + OAuth2AndOIDCConst.Basic, + CustomEncode.ToBase64String(CustomEncode.StringToByte(secretKey, CustomEncode.us_ascii))); if (ASPNETIdentityConfig.EnableStripe) { httpRequestMessage.Content = new FormUrlEncodedContent( new Dictionary { - { "email", email }, + { OAuth2AndOIDCConst.Scope_Email, email }, { "source", token } }); } @@ -323,7 +325,7 @@ public async Task CreateaOnlinePaymentCustomerAsync(string email, strin httpRequestMessage.Content = new FormUrlEncodedContent( new Dictionary { - { "email", email }, + { OAuth2AndOIDCConst.Scope_Email, email }, { "card", token } }); } @@ -378,7 +380,8 @@ public async Task ChargeToOnlinePaymentCustomersAsync(string customerId // HttpRequestMessage (Headers) httpRequestMessage.Headers.Authorization = new AuthenticationHeaderValue( - "Basic", CustomEncode.ToBase64String(CustomEncode.StringToByte(secretKey, CustomEncode.us_ascii))); + OAuth2AndOIDCConst.Basic, + CustomEncode.ToBase64String(CustomEncode.StringToByte(secretKey, CustomEncode.us_ascii))); httpRequestMessage.Content = new FormUrlEncodedContent( new Dictionary diff --git a/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ViewModels/ManageAddOAuth2DataViewModel.cs b/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ViewModels/ManageAddOAuth2DataViewModel.cs index 5c48f1c4..2df165a5 100644 --- a/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ViewModels/ManageAddOAuth2DataViewModel.cs +++ b/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ViewModels/ManageAddOAuth2DataViewModel.cs @@ -18,10 +18,14 @@ //* 2017/06/07 西野 大介 新規 //********************************************************************************** -using Newtonsoft.Json; -using System.ComponentModel.DataAnnotations; using MultiPurposeAuthSite.Models.ASPNETIdentity; +using System.ComponentModel.DataAnnotations; + +using Newtonsoft.Json; + +using Touryo.Infrastructure.Framework.Authentication; + /// MultiPurposeAuthSite.Models.ViewModels namespace MultiPurposeAuthSite.Models.ViewModels { @@ -71,7 +75,7 @@ public class ManageAddOAuth2DataViewModel : BaseViewModel ASPNETIdentityConst.MaxLengthOfClientName, ErrorMessageResourceName = "MaxLengthErrMsg", ErrorMessageResourceType = typeof(Resources.CommonViewModels))] - [JsonProperty(PropertyName = "sub")] + [JsonProperty(PropertyName = OAuth2AndOIDCConst.sub)] public string ClientName { get; set; } } } \ No newline at end of file diff --git a/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ViewModels/OAuthAuthorizationCodeGrantClientViewModel.cs b/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ViewModels/OAuth2AuthorizationCodeGrantClientViewModel.cs similarity index 90% rename from root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ViewModels/OAuthAuthorizationCodeGrantClientViewModel.cs rename to root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ViewModels/OAuth2AuthorizationCodeGrantClientViewModel.cs index 8674a50c..e259d136 100644 --- a/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ViewModels/OAuthAuthorizationCodeGrantClientViewModel.cs +++ b/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Models/ViewModels/OAuth2AuthorizationCodeGrantClientViewModel.cs @@ -21,7 +21,7 @@ #endregion //********************************************************************************** -//* クラス名 :OAuthAuthorizationCodeGrantClientViewModel +//* クラス名 :OAuth2AuthorizationCodeGrantClientViewModel //* クラス日本語名 :Claimを返すための共通ViewModel //* //* 作成日時 :- @@ -39,9 +39,9 @@ /// MultiPurposeAuthSite.Models.ViewModels namespace MultiPurposeAuthSite.Models.ViewModels { - /// OAuthAuthorizationCodeGrantClient画面のViewModel(ライブラリ) + /// OAuth2AuthorizationCodeGrantClient画面のViewModel(ライブラリ) [Serializable] - public class OAuthAuthorizationCodeGrantClientViewModel : BaseViewModel + public class OAuth2AuthorizationCodeGrantClientViewModel : BaseViewModel { /// State [Display(Name = "State")] diff --git a/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/MultiPurposeAuthSite.csproj b/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/MultiPurposeAuthSite.csproj index 18b28c84..639cdc8d 100644 --- a/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/MultiPurposeAuthSite.csproj +++ b/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/MultiPurposeAuthSite.csproj @@ -1,6 +1,6 @@  - + Debug @@ -287,7 +287,7 @@ - + @@ -298,7 +298,6 @@ - @@ -354,7 +353,7 @@ - + True @@ -481,9 +480,9 @@ - - - + + + @@ -516,12 +515,13 @@ - + - - + + + @@ -617,6 +617,12 @@ + + + このプロジェクトは、このコンピューター上にない NuGet パッケージを参照しています。それらのパッケージをダウンロードするには、[NuGet パッケージの復元] を使用します。詳細については、http://go.microsoft.com/fwlink/?LinkID=322105 を参照してください。見つからないファイルは {0} です。 + + + +} + +

@ViewBag.Title

+

@ManageViews.ManageGdprPersonalDataH4

+ +@using (Html.BeginForm("ReferGdprPersonalData", "Manage", FormMethod.Post, new { @class = "form-horizontal", role = "form" })) // FileのDLは二重送信防止しない +{ + @Html.AntiForgeryToken() + @Html.ValidationSummary("", new { @class = "text-danger" }) +
+
+ + +
+
+} + +@using (Html.BeginForm("DeleteGdprPersonalData", "Manage", FormMethod.Post, new { @class = "form-horizontal", role = "form", onsubmit = "Fx_OnSubmit();" })) +{ + @Html.AntiForgeryToken() + @Html.ValidationSummary("", new { @class = "text-danger" }) +
+
+ +
+
+} + +@* スクリプト・セクション(RenderSection("FooterScriptsSection", required: true)に出力されます) *@ +@section FooterScriptsSection{ + +} diff --git a/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Views/Manage/OAuthAuthorizationCodeGrantClient.cshtml b/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Views/Manage/OAuth2AuthorizationCodeGrantClient.cshtml similarity index 83% rename from root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Views/Manage/OAuthAuthorizationCodeGrantClient.cshtml rename to root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Views/Manage/OAuth2AuthorizationCodeGrantClient.cshtml index 46a862da..ce22b0e5 100644 --- a/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Views/Manage/OAuthAuthorizationCodeGrantClient.cshtml +++ b/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Views/Manage/OAuth2AuthorizationCodeGrantClient.cshtml @@ -7,8 +7,8 @@ // https://github.com/OpenTouryoProject/MultiPurposeAuthSite/blob/master/license/LicenseForTemplates.txt //********************************************************************************** - //* クラス名 :OAuthAuthorizationCodeGrantClient2 - //* クラス日本語名 :OAuthAuthorizationCodeGrantClient2 + //* クラス名 :OAuth2AuthorizationCodeGrantClient2 + //* クラス日本語名 :OAuth2AuthorizationCodeGrantClient2 //* //* 作成日時 :- //* 作成者 :- @@ -23,9 +23,9 @@ @*@using MultiPurposeAuthSite.Models.ASPNETIdentity*@ @using MultiPurposeAuthSite.Models.ViewModels -@model OAuthAuthorizationCodeGrantClientViewModel +@model OAuth2AuthorizationCodeGrantClientViewModel @{ - ViewBag.Title = "OAuthAuthorizationCodeGrantClient"; + ViewBag.Title = "OAuth2AuthorizationCodeGrantClient"; } @* スクリプト・セクション(RenderSection("HeaderScriptsSection", required: true)に出力されます) *@ @@ -35,7 +35,7 @@

@ViewBag.Title.


-@using (Html.BeginForm("OAuthAuthorizationCodeGrantClient2", "Manage", FormMethod.Post, new { @class = "form-horizontal", role = "form", onsubmit = "Fx_OnSubmit();" })) +@using (Html.BeginForm("OAuth2AuthorizationCodeGrantClient2", "Manage", FormMethod.Post, new { @class = "form-horizontal", role = "form", onsubmit = "Fx_OnSubmit();" })) { @Html.AntiForgeryToken() diff --git a/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Views/Shared/_Layout.cshtml b/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Views/Shared/_Layout.cshtml index 761e59e0..0c339b2e 100644 --- a/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Views/Shared/_Layout.cshtml +++ b/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Views/Shared/_Layout.cshtml @@ -129,7 +129,7 @@ else }
  • - @Html.ActionLink("OAuth Starters", "OAuthStarters", "Home", null, new { style = "color:peachpuff" }) + @Html.ActionLink("OAuth Starters", "OAuth2Starters", "Home", null, new { style = "color:peachpuff" })
  • diff --git a/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Web.config b/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Web.config index 4fd97433..fc63b9a5 100644 --- a/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Web.config +++ b/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/Web.config @@ -114,40 +114,39 @@ - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + diff --git a/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/app.config b/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/app.config index 8a363f2f..20210833 100644 --- a/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/app.config +++ b/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/app.config @@ -12,17 +12,14 @@ - - - - - + + - + @@ -40,7 +37,7 @@ - + @@ -108,7 +105,7 @@ - + @@ -143,7 +140,7 @@ - + @@ -160,6 +157,7 @@ + @@ -180,7 +178,7 @@ - + @@ -188,51 +186,51 @@ - + - + - - - - + + + + - + - - - + + + - + - + - + - + - + - + - + - + - + @@ -241,28 +239,28 @@ - + - - + + - + - + - + - - + - + - + + + + + + + - - + diff --git a/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/packages.config b/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/packages.config index 857749bf..56e387d0 100644 --- a/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/packages.config +++ b/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSite/packages.config @@ -37,7 +37,7 @@ - + diff --git a/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSiteAll.sln b/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSiteAll.sln new file mode 100644 index 00000000..ae6034e9 --- /dev/null +++ b/root/programs/MultiPurposeAuthSite/MultiPurposeAuthSiteAll.sln @@ -0,0 +1,58 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MultiPurposeAuthSite", "MultiPurposeAuthSite\MultiPurposeAuthSite.csproj", "{4BA4D9DE-2656-4FBD-8F1F-31FC9583B5F5}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CreateClientsIdentity", "CreateClientsIdentity\CreateClientsIdentity.csproj", "{9176504B-F14B-4C59-8601-5C04BE9A889D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CreateJwtBearerTokenFlowAssertion", "CreateJwtBearerTokenFlowAssertion\CreateJwtBearerTokenFlowAssertion.csproj", "{4AB3D69C-314D-4CF2-8A3A-F8E1536BFA3F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CreateJwkSetJson", "CreateJwkSetJson\CreateJwkSetJson.csproj", "{5E268E70-CCCC-4629-A442-F077FAB243A1}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {4BA4D9DE-2656-4FBD-8F1F-31FC9583B5F5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4BA4D9DE-2656-4FBD-8F1F-31FC9583B5F5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4BA4D9DE-2656-4FBD-8F1F-31FC9583B5F5}.Debug|x86.ActiveCfg = Debug|Any CPU + {4BA4D9DE-2656-4FBD-8F1F-31FC9583B5F5}.Debug|x86.Build.0 = Debug|Any CPU + {4BA4D9DE-2656-4FBD-8F1F-31FC9583B5F5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4BA4D9DE-2656-4FBD-8F1F-31FC9583B5F5}.Release|Any CPU.Build.0 = Release|Any CPU + {4BA4D9DE-2656-4FBD-8F1F-31FC9583B5F5}.Release|x86.ActiveCfg = Release|Any CPU + {4BA4D9DE-2656-4FBD-8F1F-31FC9583B5F5}.Release|x86.Build.0 = Release|Any CPU + {9176504B-F14B-4C59-8601-5C04BE9A889D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9176504B-F14B-4C59-8601-5C04BE9A889D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9176504B-F14B-4C59-8601-5C04BE9A889D}.Debug|x86.ActiveCfg = Debug|Any CPU + {9176504B-F14B-4C59-8601-5C04BE9A889D}.Debug|x86.Build.0 = Debug|Any CPU + {9176504B-F14B-4C59-8601-5C04BE9A889D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9176504B-F14B-4C59-8601-5C04BE9A889D}.Release|Any CPU.Build.0 = Release|Any CPU + {9176504B-F14B-4C59-8601-5C04BE9A889D}.Release|x86.ActiveCfg = Release|Any CPU + {9176504B-F14B-4C59-8601-5C04BE9A889D}.Release|x86.Build.0 = Release|Any CPU + {4AB3D69C-314D-4CF2-8A3A-F8E1536BFA3F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4AB3D69C-314D-4CF2-8A3A-F8E1536BFA3F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4AB3D69C-314D-4CF2-8A3A-F8E1536BFA3F}.Debug|x86.ActiveCfg = Debug|Any CPU + {4AB3D69C-314D-4CF2-8A3A-F8E1536BFA3F}.Debug|x86.Build.0 = Debug|Any CPU + {4AB3D69C-314D-4CF2-8A3A-F8E1536BFA3F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4AB3D69C-314D-4CF2-8A3A-F8E1536BFA3F}.Release|Any CPU.Build.0 = Release|Any CPU + {4AB3D69C-314D-4CF2-8A3A-F8E1536BFA3F}.Release|x86.ActiveCfg = Release|Any CPU + {4AB3D69C-314D-4CF2-8A3A-F8E1536BFA3F}.Release|x86.Build.0 = Release|Any CPU + {5E268E70-CCCC-4629-A442-F077FAB243A1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5E268E70-CCCC-4629-A442-F077FAB243A1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5E268E70-CCCC-4629-A442-F077FAB243A1}.Debug|x86.ActiveCfg = Debug|Any CPU + {5E268E70-CCCC-4629-A442-F077FAB243A1}.Debug|x86.Build.0 = Debug|Any CPU + {5E268E70-CCCC-4629-A442-F077FAB243A1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5E268E70-CCCC-4629-A442-F077FAB243A1}.Release|Any CPU.Build.0 = Release|Any CPU + {5E268E70-CCCC-4629-A442-F077FAB243A1}.Release|x86.ActiveCfg = Release|Any CPU + {5E268E70-CCCC-4629-A442-F077FAB243A1}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/root/programs/MultiPurposeAuthSiteCore/README.md b/root/programs/MultiPurposeAuthSiteCore/README.md new file mode 100644 index 00000000..a0c81b21 --- /dev/null +++ b/root/programs/MultiPurposeAuthSiteCore/README.md @@ -0,0 +1 @@ +2019年度 .NET Core 版を追加する予定。 \ No newline at end of file diff --git a/root/programs/nuget.exe b/root/programs/nuget.exe index 6d83a0b4..ccb2979c 100644 Binary files a/root/programs/nuget.exe and b/root/programs/nuget.exe differ