From 0c59e4bb9c56506af5cbf8de0b7fb2c661a87ee4 Mon Sep 17 00:00:00 2001 From: Lucas Farris Date: Thu, 11 Jan 2018 19:51:04 +0100 Subject: [PATCH 01/18] Added the End Session request/response for the RP-Initiated Logout --- AppAuth.xcodeproj/project.pbxproj | 72 ++++++++++ Source/AppAuth.h | 2 + Source/Framework/AppAuth.h | 2 + Source/OIDEndSessionRequest.h | 110 +++++++++++++++ Source/OIDEndSessionRequest.m | 187 ++++++++++++++++++++++++++ Source/OIDEndSessionResponse.h | 62 +++++++++ Source/OIDEndSessionResponse.m | 84 ++++++++++++ Source/OIDServiceDiscovery.h | 6 + Source/OIDServiceDiscovery.m | 5 + UnitTests/OIDEndSessionRequestTests.h | 31 +++++ UnitTests/OIDEndSessionRequestTests.m | 124 +++++++++++++++++ UnitTests/OIDServiceDiscoveryTests.m | 3 + 12 files changed, 688 insertions(+) create mode 100644 Source/OIDEndSessionRequest.h create mode 100644 Source/OIDEndSessionRequest.m create mode 100644 Source/OIDEndSessionResponse.h create mode 100644 Source/OIDEndSessionResponse.m create mode 100644 UnitTests/OIDEndSessionRequestTests.h create mode 100644 UnitTests/OIDEndSessionRequestTests.m diff --git a/AppAuth.xcodeproj/project.pbxproj b/AppAuth.xcodeproj/project.pbxproj index 6657b7c8b..74e8bcd75 100644 --- a/AppAuth.xcodeproj/project.pbxproj +++ b/AppAuth.xcodeproj/project.pbxproj @@ -377,6 +377,36 @@ 60140F801DE4344200DA0DC3 /* OIDRegistrationResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = 60140F7F1DE4344200DA0DC3 /* OIDRegistrationResponse.m */; }; 60140F831DE43BAF00DA0DC3 /* OIDRegistrationRequestTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 60140F821DE43BAF00DA0DC3 /* OIDRegistrationRequestTests.m */; }; 60140F861DE43CC700DA0DC3 /* OIDRegistrationResponseTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 60140F851DE43CC700DA0DC3 /* OIDRegistrationResponseTests.m */; }; + A6CEB11A2007E49C009D492A /* OIDEndSessionRequestTests.m in Sources */ = {isa = PBXBuildFile; fileRef = A6CEB1182007E384009D492A /* OIDEndSessionRequestTests.m */; }; + A6CEB11B2007E49D009D492A /* OIDEndSessionRequestTests.m in Sources */ = {isa = PBXBuildFile; fileRef = A6CEB1182007E384009D492A /* OIDEndSessionRequestTests.m */; }; + A6CEB11C2007E49E009D492A /* OIDEndSessionRequestTests.m in Sources */ = {isa = PBXBuildFile; fileRef = A6CEB1182007E384009D492A /* OIDEndSessionRequestTests.m */; }; + A6CEB11D2007E49F009D492A /* OIDEndSessionRequestTests.m in Sources */ = {isa = PBXBuildFile; fileRef = A6CEB1182007E384009D492A /* OIDEndSessionRequestTests.m */; }; + A6CEB11E2007E4A1009D492A /* OIDEndSessionRequestTests.m in Sources */ = {isa = PBXBuildFile; fileRef = A6CEB1182007E384009D492A /* OIDEndSessionRequestTests.m */; }; + A6CEB11F2007E4A2009D492A /* OIDEndSessionRequestTests.m in Sources */ = {isa = PBXBuildFile; fileRef = A6CEB1182007E384009D492A /* OIDEndSessionRequestTests.m */; }; + A6DEAB832017A7030022AC32 /* OIDEndSessionResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = CF6431F31F228A980075B6B5 /* OIDEndSessionResponse.m */; }; + A6DEAB842017A7040022AC32 /* OIDEndSessionResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = CF6431F31F228A980075B6B5 /* OIDEndSessionResponse.m */; }; + A6DEAB852017A7050022AC32 /* OIDEndSessionResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = CF6431F31F228A980075B6B5 /* OIDEndSessionResponse.m */; }; + A6DEAB862017A7060022AC32 /* OIDEndSessionResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = CF6431F31F228A980075B6B5 /* OIDEndSessionResponse.m */; }; + A6DEAB872017A70B0022AC32 /* OIDEndSessionResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = CF6431F31F228A980075B6B5 /* OIDEndSessionResponse.m */; }; + A6DEAB882017A70B0022AC32 /* OIDEndSessionResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = CF6431F31F228A980075B6B5 /* OIDEndSessionResponse.m */; }; + A6DEAB892017A70C0022AC32 /* OIDEndSessionResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = CF6431F31F228A980075B6B5 /* OIDEndSessionResponse.m */; }; + A6DEAB8A2017A7140022AC32 /* OIDEndSessionRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = CF37C06C1F1FC21A00662E41 /* OIDEndSessionRequest.m */; }; + A6DEAB8B2017A7160022AC32 /* OIDEndSessionRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = CF37C06C1F1FC21A00662E41 /* OIDEndSessionRequest.m */; }; + A6DEAB8C2017A7160022AC32 /* OIDEndSessionRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = CF37C06C1F1FC21A00662E41 /* OIDEndSessionRequest.m */; }; + A6DEAB8D2017A7170022AC32 /* OIDEndSessionRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = CF37C06C1F1FC21A00662E41 /* OIDEndSessionRequest.m */; }; + A6DEABB02018ECE80022AC32 /* OIDEndSessionRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = CF37C06B1F1FC21A00662E41 /* OIDEndSessionRequest.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A6DEABB12018ECE80022AC32 /* OIDEndSessionRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = CF37C06B1F1FC21A00662E41 /* OIDEndSessionRequest.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A6DEABB22018ECE90022AC32 /* OIDEndSessionRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = CF37C06B1F1FC21A00662E41 /* OIDEndSessionRequest.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A6DEABB32018ECE90022AC32 /* OIDEndSessionRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = CF37C06B1F1FC21A00662E41 /* OIDEndSessionRequest.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A6DEABB42018ECF20022AC32 /* OIDEndSessionResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = CF6431F21F228A980075B6B5 /* OIDEndSessionResponse.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A6DEABB52018ECF30022AC32 /* OIDEndSessionResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = CF6431F21F228A980075B6B5 /* OIDEndSessionResponse.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A6DEABB62018ECF30022AC32 /* OIDEndSessionResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = CF6431F21F228A980075B6B5 /* OIDEndSessionResponse.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A6DEABB72018ECF40022AC32 /* OIDEndSessionResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = CF6431F21F228A980075B6B5 /* OIDEndSessionResponse.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CF37C06E1F1FC21A00662E41 /* OIDEndSessionRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = CF37C06C1F1FC21A00662E41 /* OIDEndSessionRequest.m */; }; + CF37C06F1F1FC21A00662E41 /* OIDEndSessionRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = CF37C06C1F1FC21A00662E41 /* OIDEndSessionRequest.m */; }; + CF37C0701F1FC21A00662E41 /* OIDEndSessionRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = CF37C06C1F1FC21A00662E41 /* OIDEndSessionRequest.m */; }; + CF37C0711F1FC21A00662E41 /* OIDEndSessionRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = CF37C06C1F1FC21A00662E41 /* OIDEndSessionRequest.m */; }; + CF6431F41F228A980075B6B5 /* OIDEndSessionResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = CF6431F31F228A980075B6B5 /* OIDEndSessionResponse.m */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -557,6 +587,12 @@ 60140F821DE43BAF00DA0DC3 /* OIDRegistrationRequestTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OIDRegistrationRequestTests.m; sourceTree = ""; }; 60140F841DE43C8C00DA0DC3 /* OIDRegistrationResponseTests.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OIDRegistrationResponseTests.h; sourceTree = ""; }; 60140F851DE43CC700DA0DC3 /* OIDRegistrationResponseTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OIDRegistrationResponseTests.m; sourceTree = ""; }; + A6CEB1172007E384009D492A /* OIDEndSessionRequestTests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OIDEndSessionRequestTests.h; sourceTree = ""; }; + A6CEB1182007E384009D492A /* OIDEndSessionRequestTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OIDEndSessionRequestTests.m; sourceTree = ""; }; + CF37C06B1F1FC21A00662E41 /* OIDEndSessionRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OIDEndSessionRequest.h; sourceTree = ""; }; + CF37C06C1F1FC21A00662E41 /* OIDEndSessionRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OIDEndSessionRequest.m; sourceTree = ""; }; + CF6431F21F228A980075B6B5 /* OIDEndSessionResponse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OIDEndSessionResponse.h; sourceTree = ""; }; + CF6431F31F228A980075B6B5 /* OIDEndSessionResponse.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OIDEndSessionResponse.m; sourceTree = ""; }; F68103B61D2568D10053658E /* OIDAuthorizationUICoordinator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OIDAuthorizationUICoordinator.h; sourceTree = ""; }; F6F60FB01D2BFEFE00325CB3 /* OIDAuthState+IOS.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "OIDAuthState+IOS.m"; path = "iOS/OIDAuthState+IOS.m"; sourceTree = ""; }; F6F60FB11D2BFEFE00325CB3 /* OIDAuthorizationService+IOS.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "OIDAuthorizationService+IOS.m"; path = "iOS/OIDAuthorizationService+IOS.m"; sourceTree = ""; }; @@ -750,6 +786,10 @@ 341741C21C5D8243000EF209 /* OIDErrorUtilities.m */, 341741C31C5D8243000EF209 /* OIDFieldMapping.h */, 341741C41C5D8243000EF209 /* OIDFieldMapping.m */, + CF6431F21F228A980075B6B5 /* OIDEndSessionResponse.h */, + CF6431F31F228A980075B6B5 /* OIDEndSessionResponse.m */, + CF37C06B1F1FC21A00662E41 /* OIDEndSessionRequest.h */, + CF37C06C1F1FC21A00662E41 /* OIDEndSessionRequest.m */, 60140F7E1DE4335200DA0DC3 /* OIDRegistrationResponse.h */, 60140F7F1DE4344200DA0DC3 /* OIDRegistrationResponse.m */, 60140F7D1DE42E3000DA0DC3 /* OIDRegistrationRequest.h */, @@ -793,6 +833,8 @@ 60140F811DE43B4D00DA0DC3 /* OIDRegistrationRequestTests.h */, 341742061C5D82D3000EF209 /* OIDGrantTypesTests.m */, 341742071C5D82D3000EF209 /* OIDResponseTypesTests.m */, + A6CEB1172007E384009D492A /* OIDEndSessionRequestTests.h */, + A6CEB1182007E384009D492A /* OIDEndSessionRequestTests.m */, 341742081C5D82D3000EF209 /* OIDScopesTests.m */, 341742091C5D82D3000EF209 /* OIDServiceConfigurationTests.h */, 3417420A1C5D82D3000EF209 /* OIDServiceConfigurationTests.m */, @@ -880,6 +922,7 @@ 343AAAF71E83499000F9D36E /* OIDTokenRequest.h in Headers */, 343AAAF41E83499000F9D36E /* OIDScopeUtilities.h in Headers */, 343AAAF81E83499000F9D36E /* OIDTokenResponse.h in Headers */, + A6DEABB42018ECF20022AC32 /* OIDEndSessionResponse.h in Headers */, 343AAAF61E83499000F9D36E /* OIDServiceDiscovery.h in Headers */, 343AAAF11E83499000F9D36E /* OIDGrantTypes.h in Headers */, 343AAA6D1E83466B00F9D36E /* OIDAuthState+IOS.h in Headers */, @@ -889,6 +932,7 @@ 343AAAE51E83499000F9D36E /* OIDAuthorizationService.h in Headers */, 343AAAF01E83499000F9D36E /* OIDRegistrationRequest.h in Headers */, 343AAAE61E83499000F9D36E /* OIDAuthorizationUICoordinator.h in Headers */, + A6DEABB02018ECE80022AC32 /* OIDEndSessionRequest.h in Headers */, 343AAAE71E83499000F9D36E /* OIDAuthState.h in Headers */, 343AAAED1E83499000F9D36E /* OIDErrorUtilities.h in Headers */, 343AAA6C1E83466B00F9D36E /* OIDAuthorizationService+IOS.h in Headers */, @@ -905,6 +949,7 @@ 343AAB041E83499100F9D36E /* OIDError.h in Headers */, 343AAB091E83499100F9D36E /* OIDGrantTypes.h in Headers */, 343AAAFF1E83499100F9D36E /* OIDAuthState.h in Headers */, + A6DEABB52018ECF30022AC32 /* OIDEndSessionResponse.h in Headers */, 343AAB0D1E83499100F9D36E /* OIDServiceConfiguration.h in Headers */, 343AAAFD1E83499100F9D36E /* OIDAuthorizationService.h in Headers */, 343AAB0F1E83499100F9D36E /* OIDTokenRequest.h in Headers */, @@ -914,6 +959,7 @@ 343AAB0A1E83499100F9D36E /* OIDResponseTypes.h in Headers */, 343AAB0B1E83499100F9D36E /* OIDScopes.h in Headers */, 343AAB9B1E834A8800F9D36E /* AppAuth.h in Headers */, + A6DEABB12018ECE80022AC32 /* OIDEndSessionRequest.h in Headers */, 343AAB001E83499100F9D36E /* OIDAuthStateChangeDelegate.h in Headers */, 343AAB081E83499100F9D36E /* OIDRegistrationRequest.h in Headers */, 343AAB101E83499100F9D36E /* OIDTokenResponse.h in Headers */, @@ -933,6 +979,7 @@ 343AAB1C1E83499200F9D36E /* OIDError.h in Headers */, 343AAB211E83499200F9D36E /* OIDGrantTypes.h in Headers */, 343AAB171E83499200F9D36E /* OIDAuthState.h in Headers */, + A6DEABB62018ECF30022AC32 /* OIDEndSessionResponse.h in Headers */, 343AAB251E83499200F9D36E /* OIDServiceConfiguration.h in Headers */, 343AAB151E83499200F9D36E /* OIDAuthorizationService.h in Headers */, 343AAB271E83499200F9D36E /* OIDTokenRequest.h in Headers */, @@ -942,6 +989,7 @@ 343AAB221E83499200F9D36E /* OIDResponseTypes.h in Headers */, 343AAB231E83499200F9D36E /* OIDScopes.h in Headers */, 343AAB9C1E834A8900F9D36E /* AppAuth.h in Headers */, + A6DEABB22018ECE90022AC32 /* OIDEndSessionRequest.h in Headers */, 343AAB181E83499200F9D36E /* OIDAuthStateChangeDelegate.h in Headers */, 343AAB201E83499200F9D36E /* OIDRegistrationRequest.h in Headers */, 343AAB281E83499200F9D36E /* OIDTokenResponse.h in Headers */, @@ -963,6 +1011,7 @@ 343AAAE01E83494400F9D36E /* OIDAuthState+Mac.h in Headers */, 343AAADD1E83494400F9D36E /* OIDRedirectHTTPHandler.h in Headers */, 343AAB3C1E83499200F9D36E /* OIDScopeUtilities.h in Headers */, + A6DEABB32018ECE90022AC32 /* OIDEndSessionRequest.h in Headers */, 343AAB3F1E83499200F9D36E /* OIDTokenRequest.h in Headers */, 343AAB411E83499200F9D36E /* OIDTokenUtilities.h in Headers */, 343AAB371E83499200F9D36E /* OIDRegistrationResponse.h in Headers */, @@ -972,6 +1021,7 @@ 343AAB3D1E83499200F9D36E /* OIDServiceConfiguration.h in Headers */, 343AAB351E83499200F9D36E /* OIDErrorUtilities.h in Headers */, 343AAB391E83499200F9D36E /* OIDGrantTypes.h in Headers */, + A6DEABB72018ECF40022AC32 /* OIDEndSessionResponse.h in Headers */, 343AAB341E83499200F9D36E /* OIDError.h in Headers */, 343AAB401E83499200F9D36E /* OIDTokenResponse.h in Headers */, 343AAB3A1E83499200F9D36E /* OIDResponseTypes.h in Headers */, @@ -1425,6 +1475,8 @@ 341310CC1E6F944B00D5DEE5 /* OIDServiceDiscovery.m in Sources */, 341310CA1E6F944B00D5DEE5 /* OIDScopeUtilities.m in Sources */, 340DAE5C1D5821AB00EC285B /* OIDAuthorizationService.m in Sources */, + CF37C06F1F1FC21A00662E41 /* OIDEndSessionRequest.m in Sources */, + A6DEAB832017A7030022AC32 /* OIDEndSessionResponse.m in Sources */, 341310CD1E6F944B00D5DEE5 /* OIDTokenRequest.m in Sources */, 341310C91E6F944B00D5DEE5 /* OIDScopes.m in Sources */, 341310CE1E6F944B00D5DEE5 /* OIDTokenResponse.m in Sources */, @@ -1445,6 +1497,7 @@ buildActionMask = 2147483647; files = ( 341741E01C5D8243000EF209 /* OIDErrorUtilities.m in Sources */, + CF6431F41F228A980075B6B5 /* OIDEndSessionResponse.m in Sources */, 341741EA1C5D8243000EF209 /* OIDTokenUtilities.m in Sources */, 341741E21C5D8243000EF209 /* OIDGrantTypes.m in Sources */, 60140F7C1DE42E1000DA0DC3 /* OIDRegistrationRequest.m in Sources */, @@ -1456,6 +1509,7 @@ 341741E61C5D8243000EF209 /* OIDServiceConfiguration.m in Sources */, 60140F7A1DE4276800DA0DC3 /* OIDClientMetadataParameters.m in Sources */, 341741DE1C5D8243000EF209 /* OIDAuthState.m in Sources */, + CF37C06E1F1FC21A00662E41 /* OIDEndSessionRequest.m in Sources */, 341741DD1C5D8243000EF209 /* OIDAuthorizationService.m in Sources */, 340DAECD1D582DE100EC285B /* OIDAuthorizationUICoordinatorIOS.m in Sources */, 341741EB1C5D8243000EF209 /* OIDURLQueryComponent.m in Sources */, @@ -1484,6 +1538,7 @@ 341742181C5D82D3000EF209 /* OIDAuthorizationResponseTests.m in Sources */, 341742171C5D82D3000EF209 /* OIDAuthorizationRequestTests.m in Sources */, 0396974D1FA827AD003D1FB2 /* OIDURLSessionProviderTests.m in Sources */, + A6CEB11A2007E49C009D492A /* OIDEndSessionRequestTests.m in Sources */, 3417421A1C5D82D3000EF209 /* OIDGrantTypesTests.m in Sources */, 3417421B1C5D82D3000EF209 /* OIDResponseTypesTests.m in Sources */, 60140F831DE43BAF00DA0DC3 /* OIDRegistrationRequestTests.m in Sources */, @@ -1500,6 +1555,7 @@ files = ( 341AA50A1E7F3A9B00FCA5C6 /* OIDScopesTests.m in Sources */, 341AA50F1E7F3A9B00FCA5C6 /* OIDURLQueryComponentTests.m in Sources */, + A6CEB11B2007E49D009D492A /* OIDEndSessionRequestTests.m in Sources */, 341AA50B1E7F3A9B00FCA5C6 /* OIDServiceConfigurationTests.m in Sources */, 341AA50C1E7F3A9B00FCA5C6 /* OIDServiceDiscoveryTests.m in Sources */, 341AA5071E7F3A9B00FCA5C6 /* OIDAuthStateTests.m in Sources */, @@ -1520,6 +1576,7 @@ files = ( 341AA4FD1E7F3A9400FCA5C6 /* OIDScopesTests.m in Sources */, 341AA5021E7F3A9400FCA5C6 /* OIDURLQueryComponentTests.m in Sources */, + A6CEB11C2007E49E009D492A /* OIDEndSessionRequestTests.m in Sources */, 341AA4FE1E7F3A9400FCA5C6 /* OIDServiceConfigurationTests.m in Sources */, 341AA4FF1E7F3A9400FCA5C6 /* OIDServiceDiscoveryTests.m in Sources */, 341AA4FA1E7F3A9400FCA5C6 /* OIDAuthStateTests.m in Sources */, @@ -1551,12 +1608,14 @@ 341310D31E6F944D00D5DEE5 /* OIDError.m in Sources */, 341310DE1E6F944D00D5DEE5 /* OIDTokenRequest.m in Sources */, 341310DF1E6F944D00D5DEE5 /* OIDTokenResponse.m in Sources */, + A6DEAB842017A7040022AC32 /* OIDEndSessionResponse.m in Sources */, 341310DC1E6F944D00D5DEE5 /* OIDServiceConfiguration.m in Sources */, 341310BF1E6F943C00D5DEE5 /* OIDClientMetadataParameters.m in Sources */, 341310E01E6F944D00D5DEE5 /* OIDTokenUtilities.m in Sources */, 341E709A1DE18796004353C1 /* OIDAuthorizationService.m in Sources */, 341310D91E6F944D00D5DEE5 /* OIDResponseTypes.m in Sources */, 341310E11E6F944D00D5DEE5 /* OIDURLQueryComponent.m in Sources */, + CF37C0701F1FC21A00662E41 /* OIDEndSessionRequest.m in Sources */, 341310D41E6F944D00D5DEE5 /* OIDErrorUtilities.m in Sources */, 341310D81E6F944D00D5DEE5 /* OIDGrantTypes.m in Sources */, ); @@ -1567,6 +1626,7 @@ buildActionMask = 2147483647; files = ( 343AAA881E83478900F9D36E /* OIDFieldMapping.m in Sources */, + A6DEAB862017A7060022AC32 /* OIDEndSessionResponse.m in Sources */, 343AAA841E83478900F9D36E /* OIDAuthState.m in Sources */, 343AAA701E83467D00F9D36E /* OIDAuthState+IOS.m in Sources */, 343AAA921E83478900F9D36E /* OIDTokenResponse.m in Sources */, @@ -1579,6 +1639,7 @@ 343AAA931E83478900F9D36E /* OIDTokenUtilities.m in Sources */, 343AAA901E83478900F9D36E /* OIDServiceDiscovery.m in Sources */, 343AAA911E83478900F9D36E /* OIDTokenRequest.m in Sources */, + A6DEAB8A2017A7140022AC32 /* OIDEndSessionRequest.m in Sources */, 343AAA6F1E83467D00F9D36E /* OIDAuthorizationService+IOS.m in Sources */, 343AAA8F1E83478900F9D36E /* OIDServiceConfiguration.m in Sources */, 343AAA891E83478900F9D36E /* OIDRegistrationResponse.m in Sources */, @@ -1610,6 +1671,7 @@ 343AAA7F1E8346B400F9D36E /* OIDRegistrationRequestTests.m in Sources */, 343AAA731E8346B400F9D36E /* OIDAuthorizationRequestTests.m in Sources */, 343AAA761E8346B400F9D36E /* OIDGrantTypesTests.m in Sources */, + A6CEB11D2007E49F009D492A /* OIDEndSessionRequestTests.m in Sources */, 343AAA741E8346B400F9D36E /* OIDAuthorizationResponseTests.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1629,8 +1691,10 @@ 343AAB781E8349B000F9D36E /* OIDScopeUtilities.m in Sources */, 343AAB731E8349B000F9D36E /* OIDRegistrationResponse.m in Sources */, 343AAB701E8349B000F9D36E /* OIDError.m in Sources */, + A6DEAB8B2017A7160022AC32 /* OIDEndSessionRequest.m in Sources */, 343AAB7B1E8349B000F9D36E /* OIDTokenRequest.m in Sources */, 343AAB7C1E8349B000F9D36E /* OIDTokenResponse.m in Sources */, + A6DEAB872017A70B0022AC32 /* OIDEndSessionResponse.m in Sources */, 343AAB791E8349B000F9D36E /* OIDServiceConfiguration.m in Sources */, 343AAB6F1E8349B000F9D36E /* OIDClientMetadataParameters.m in Sources */, 343AAB7D1E8349B000F9D36E /* OIDTokenUtilities.m in Sources */, @@ -1657,8 +1721,10 @@ 343AAB641E8349B000F9D36E /* OIDScopeUtilities.m in Sources */, 343AAB5F1E8349B000F9D36E /* OIDRegistrationResponse.m in Sources */, 343AAB5C1E8349B000F9D36E /* OIDError.m in Sources */, + A6DEAB8C2017A7160022AC32 /* OIDEndSessionRequest.m in Sources */, 343AAB671E8349B000F9D36E /* OIDTokenRequest.m in Sources */, 343AAB681E8349B000F9D36E /* OIDTokenResponse.m in Sources */, + A6DEAB882017A70B0022AC32 /* OIDEndSessionResponse.m in Sources */, 343AAB651E8349B000F9D36E /* OIDServiceConfiguration.m in Sources */, 343AAB5B1E8349B000F9D36E /* OIDClientMetadataParameters.m in Sources */, 343AAB691E8349B000F9D36E /* OIDTokenUtilities.m in Sources */, @@ -1687,6 +1753,7 @@ 343AAB8B1E8349CE00F9D36E /* OIDRegistrationRequestTests.m in Sources */, 343AAB7F1E8349CE00F9D36E /* OIDAuthorizationRequestTests.m in Sources */, 343AAB821E8349CE00F9D36E /* OIDGrantTypesTests.m in Sources */, + A6CEB11E2007E4A1009D492A /* OIDEndSessionRequestTests.m in Sources */, 343AAB801E8349CE00F9D36E /* OIDAuthorizationResponseTests.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1699,6 +1766,7 @@ 343AAADC1E83493D00F9D36E /* OIDAuthState+Mac.m in Sources */, 343AAADA1E83493D00F9D36E /* OIDAuthorizationService+Mac.m in Sources */, 343AAB4C1E8349AF00F9D36E /* OIDRegistrationRequest.m in Sources */, + A6DEAB8D2017A7170022AC32 /* OIDEndSessionRequest.m in Sources */, 343AAB451E8349AF00F9D36E /* OIDAuthorizationService.m in Sources */, 343AAB431E8349AF00F9D36E /* OIDAuthorizationRequest.m in Sources */, 343AAAD91E83493D00F9D36E /* OIDRedirectHTTPHandler.m in Sources */, @@ -1720,6 +1788,7 @@ 34AF736D1FB4E4B40022335F /* OIDURLSessionProvider.m in Sources */, 343AAB561E8349AF00F9D36E /* OIDURLQueryComponent.m in Sources */, 343AAB4E1E8349AF00F9D36E /* OIDResponseTypes.m in Sources */, + A6DEAB892017A70C0022AC32 /* OIDEndSessionResponse.m in Sources */, 343AAB4A1E8349AF00F9D36E /* OIDFieldMapping.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1741,6 +1810,7 @@ 343AAB991E8349CF00F9D36E /* OIDRegistrationRequestTests.m in Sources */, 343AAB8D1E8349CF00F9D36E /* OIDAuthorizationRequestTests.m in Sources */, 343AAB901E8349CF00F9D36E /* OIDGrantTypesTests.m in Sources */, + A6CEB11F2007E4A2009D492A /* OIDEndSessionRequestTests.m in Sources */, 343AAB8E1E8349CF00F9D36E /* OIDAuthorizationResponseTests.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1762,12 +1832,14 @@ 347424041E7F4BA000D3E6D6 /* OIDError.m in Sources */, 3474240F1E7F4BA000D3E6D6 /* OIDTokenRequest.m in Sources */, 347424101E7F4BA000D3E6D6 /* OIDTokenResponse.m in Sources */, + A6DEAB852017A7050022AC32 /* OIDEndSessionResponse.m in Sources */, 3474240D1E7F4BA000D3E6D6 /* OIDServiceConfiguration.m in Sources */, 347424031E7F4BA000D3E6D6 /* OIDClientMetadataParameters.m in Sources */, 347424111E7F4BA000D3E6D6 /* OIDTokenUtilities.m in Sources */, 347424011E7F4BA000D3E6D6 /* OIDAuthorizationService.m in Sources */, 3474240A1E7F4BA000D3E6D6 /* OIDResponseTypes.m in Sources */, 347424121E7F4BA000D3E6D6 /* OIDURLQueryComponent.m in Sources */, + CF37C0711F1FC21A00662E41 /* OIDEndSessionRequest.m in Sources */, 347424051E7F4BA000D3E6D6 /* OIDErrorUtilities.m in Sources */, 347424091E7F4BA000D3E6D6 /* OIDGrantTypes.m in Sources */, ); diff --git a/Source/AppAuth.h b/Source/AppAuth.h index cfd3f9c62..4976616ce 100644 --- a/Source/AppAuth.h +++ b/Source/AppAuth.h @@ -37,6 +37,8 @@ #import "OIDTokenResponse.h" #import "OIDTokenUtilities.h" #import "OIDURLSessionProvider.h" +#import "OIDEndSessionRequest.h" +#import "OIDEndSessionResponse.h" #if TARGET_OS_TV #elif TARGET_OS_WATCH diff --git a/Source/Framework/AppAuth.h b/Source/Framework/AppAuth.h index 1275e36f2..24e3743ef 100644 --- a/Source/Framework/AppAuth.h +++ b/Source/Framework/AppAuth.h @@ -44,6 +44,8 @@ FOUNDATION_EXPORT const unsigned char AppAuthVersionString[]; #import #import #import +#import +#import #if TARGET_OS_TV #elif TARGET_OS_WATCH diff --git a/Source/OIDEndSessionRequest.h b/Source/OIDEndSessionRequest.h new file mode 100644 index 000000000..08e12af9a --- /dev/null +++ b/Source/OIDEndSessionRequest.h @@ -0,0 +1,110 @@ +/*! @file OIDEndSessionRequest.h + @brief AppAuth iOS SDK + @copyright + Copyright 2017 The AppAuth Authors. All Rights Reserved. + @copydetails + 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. + */ + +#import + +@class OIDServiceConfiguration; + +NS_ASSUME_NONNULL_BEGIN + +@interface OIDEndSessionRequest : NSObject { + OIDServiceConfiguration *_configuration; + NSURL *_postLogoutRedirectURL; + NSString *_idTokenHint; + NSString *_state; + NSDictionary *_additionalParameters; +} + +/*! @brief The service's configuration. + @remarks This configuration specifies how to connect to a particular OAuth provider. + Configurations may be created manually, or via an OpenID Connect Discovery Document. + */ +@property(nonatomic, readonly) OIDServiceConfiguration *configuration; + +/*! @brief The client's redirect URI. + @remarks post_logout_redirect_uri + @see http://openid.net/specs/openid-connect-session-1_0.html#RPLogout + */ +@property(nonatomic, readonly, nullable) NSURL *postLogoutRedirectURL; + +/*! @brief Previously issued ID Token passed to the end session endpoint as a hint about the End-User's current authenticated + session with the Client + @remarks id_token_hint + @see http://openid.net/specs/openid-connect-session-1_0.html#RPLogout + */ +@property(nonatomic, readonly, nullable) NSString *idTokenHint; + +/*! @brief An opaque value used by the client to maintain state between the request and callback. + @remarks state + @discussion If this value is not explicitly set, this library will automatically add state and + perform appropriate validation of the state in the authorization response. It is recommended + that the default implementation of this parameter be used wherever possible. Typically used + to prevent CSRF attacks, as recommended in RFC6819 Section 5.3.5. + @see http://openid.net/specs/openid-connect-session-1_0.html#RPLogout + */ +@property(nonatomic, readonly, nullable) NSString *state; + +/*! @brief The client's additional authorization parameters. + @see https://tools.ietf.org/html/rfc6749#section-3.1 + */ +@property(nonatomic, readonly, nullable) NSDictionary *additionalParameters; + +/*! @internal + @brief Unavailable. Please use @c initWithConfiguration:clientId:scopes:redirectURL:additionalParameters:. + */ +- (instancetype)init NS_UNAVAILABLE; + +/*! @brief Creates an authorization request with opinionated defaults (a secure @c state). + @param configuration The service's configuration. + @param idTokenHint The previously issued ID Token + @param postLogoutRedirectURL The client's post-logout redirect URI. + callback. + @param additionalParameters The client's additional authorization parameters. +*/ +- (instancetype) + initWithConfiguration:(OIDServiceConfiguration *)configuration + idTokenHint:(NSString *)idTokenHint + postLogoutRedirectURL:(NSURL *)postLogoutRedirectURL + additionalParameters:(nullable NSDictionary *)additionalParameters; + +/*! @brief Designated initializer. + @param configuration The service's configuration. + @param idTokenHint The previously issued ID Token + @param postLogoutRedirectURL The client's post-logout redirect URI. + @param state An opaque value used by the client to maintain state between the request and + callback. + @param additionalParameters The client's additional authorization parameters. + */ +- (instancetype) + initWithConfiguration:(OIDServiceConfiguration *)configuration + idTokenHint:(NSString *)idTokenHint + postLogoutRedirectURL:(NSURL *)postLogoutRedirectURL + state:(NSString *)state + additionalParameters:(nullable NSDictionary *)additionalParameters + NS_DESIGNATED_INITIALIZER; + +/*! @brief Constructs the request URI by adding the request parameters to the query component of the + authorization endpoint URI using the "application/x-www-form-urlencoded" format. + @return A URL representing the authorization request. + @see http://openid.net/specs/openid-connect-session-1_0.html#RPLogout + */ +- (NSURL *)endSessionRequestURL; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Source/OIDEndSessionRequest.m b/Source/OIDEndSessionRequest.m new file mode 100644 index 000000000..f0b51767b --- /dev/null +++ b/Source/OIDEndSessionRequest.m @@ -0,0 +1,187 @@ +/*! @file OIDEndSessionRequest.m + @brief AppAuth iOS SDK + @copyright + Copyright 2017 The AppAuth Authors. All Rights Reserved. + @copydetails + 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. + */ + +#import "OIDEndSessionRequest.h" + +#import "OIDDefines.h" +#import "OIDTokenUtilities.h" +#import "OIDServiceConfiguration.h" +#import "OIDServiceDiscovery.h" +#import "OIDURLQueryComponent.h" + +/*! @brief The key for the @c configuration property for @c NSSecureCoding + */ +static NSString *const kConfigurationKey = @"configuration"; + +/*! @brief Key used to encode the @c state property for @c NSSecureCoding, and on the URL request. + */ +static NSString *const kStateKey = @"state"; + +/*! @brief Key used to encode the @c postLogoutRedirectURL property for @c NSSecureCoding, and on the URL request. + */ +static NSString *const kPostLogoutRedirectURLKey = @"post_logout_redirect_uri"; + +/*! @brief Key used to encode the @c idTokenHint property for @c NSSecureCoding, and on the URL request. + */ +static NSString *const kIdTokenHintKey = @"id_token_hint"; + + +/*! @brief Key used to encode the @c additionalParameters property for @c NSSecureCoding + */ +static NSString *const kAdditionalParametersKey = @"additionalParameters"; + +/*! @brief Number of random bytes generated for the @state. + */ +static NSUInteger const kStateSizeBytes = 32; + +/*! @brief Assertion text for missing end_session_endpoint. + */ +static NSString *const OIDMissingEndSessionEndpointMessage = +@"The service configuration is missing an end_session_endpoint."; + +@implementation OIDEndSessionRequest + +@synthesize configuration = _configuration; +@synthesize postLogoutRedirectURL = _postLogoutRedirectURL; +@synthesize idTokenHint = _idTokenHint; +@synthesize state = _state; +@synthesize additionalParameters = _additionalParameters; + +- (instancetype)init + OID_UNAVAILABLE_USE_INITIALIZER( + @selector(initWithConfiguration: + idTokenHint: + postLogoutRedirectURL: + additionalParameters:) + ); + +- (instancetype)initWithConfiguration:(OIDServiceConfiguration *)configuration + idTokenHint:(NSString *)idTokenHint + postLogoutRedirectURL:(NSURL *)postLogoutRedirectURL + state:(NSString *)state + additionalParameters:(NSDictionary *)additionalParameters +{ + self = [super init]; + if (self) { + _configuration = [configuration copy]; + _idTokenHint = [idTokenHint copy]; + _postLogoutRedirectURL = [postLogoutRedirectURL copy]; + _state = [state copy]; + _additionalParameters = + [[NSDictionary alloc] initWithDictionary:additionalParameters copyItems:YES]; + } + return self; +} + +- (instancetype)initWithConfiguration:(OIDServiceConfiguration *)configuration + idTokenHint:(NSString *)idTokenHint + postLogoutRedirectURL:(NSURL *)postLogoutRedirectURL + additionalParameters:(NSDictionary *)additionalParameters +{ + return [self initWithConfiguration:configuration + idTokenHint:idTokenHint + postLogoutRedirectURL:postLogoutRedirectURL + state:[[self class] generateState] + additionalParameters:additionalParameters]; +} +#pragma mark - NSCopying + +- (instancetype)copyWithZone:(nullable NSZone *)zone { + // The documentation for NSCopying specifically advises us to return a reference to the original + // instance in the case where instances are immutable (as ours is): + // "Implement NSCopying by retaining the original instead of creating a new copy when the class + // and its contents are immutable." + return self; +} + +#pragma mark - NSSecureCoding + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + OIDServiceConfiguration *configuration = [aDecoder decodeObjectOfClass:[OIDServiceConfiguration class] forKey:kConfigurationKey]; + + NSString *idTokenHint = [aDecoder decodeObjectOfClass:[NSString class] forKey:kIdTokenHintKey]; + NSURL *postLogoutRedirectURL = [aDecoder decodeObjectOfClass:[NSURL class] forKey:kPostLogoutRedirectURLKey]; + NSString *state = [aDecoder decodeObjectOfClass:[NSString class] forKey:kStateKey]; + NSSet *additionalParameterCodingClasses = [NSSet setWithArray:@[ + [NSDictionary class], + [NSString class] + ]]; + NSDictionary *additionalParameters = [aDecoder decodeObjectOfClasses:additionalParameterCodingClasses + forKey:kAdditionalParametersKey]; + + self = [self initWithConfiguration:configuration + idTokenHint:idTokenHint + postLogoutRedirectURL:postLogoutRedirectURL + state:state + additionalParameters:additionalParameters]; + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:_configuration forKey:kConfigurationKey]; + [aCoder encodeObject:_idTokenHint forKey:kIdTokenHintKey]; + [aCoder encodeObject:_postLogoutRedirectURL forKey:kPostLogoutRedirectURLKey]; + [aCoder encodeObject:_state forKey:kStateKey]; + [aCoder encodeObject:_additionalParameters forKey:kAdditionalParametersKey]; +} + +#pragma mark - NSObject overrides + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@: %p, request: %@>", + NSStringFromClass([self class]), + self, + self.endSessionRequestURL]; +} + ++ (nullable NSString *)generateState { + return [OIDTokenUtilities randomURLSafeStringWithSize:kStateSizeBytes]; +} + +#pragma mark - + +- (NSURL *)endSessionRequestURL { + OIDURLQueryComponent *query = [[OIDURLQueryComponent alloc] init]; + + // Add any additional parameters the client has specified. + [query addParameters:_additionalParameters]; + + // Add optional parameters, as applicable. + if (_idTokenHint) { + [query addParameter:kIdTokenHintKey value:_idTokenHint]; + } + + if (_postLogoutRedirectURL) { + [query addParameter:kPostLogoutRedirectURLKey value:_postLogoutRedirectURL.absoluteString]; + } + + if (_state) { + [query addParameter:kStateKey value:_state]; + } + + NSAssert(_configuration.discoveryDocument.endSessionEndpoint, OIDMissingEndSessionEndpointMessage); + + // Construct the URL: + return [query URLByReplacingQueryInURL:_configuration.discoveryDocument.endSessionEndpoint]; +} + +@end diff --git a/Source/OIDEndSessionResponse.h b/Source/OIDEndSessionResponse.h new file mode 100644 index 000000000..6fc0131c3 --- /dev/null +++ b/Source/OIDEndSessionResponse.h @@ -0,0 +1,62 @@ +/*! @file OIDEndSessionResponse.h + @brief AppAuth iOS SDK + @copyright + Copyright 2017 The AppAuth Authors. All Rights Reserved. + @copydetails + 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. + */ + +#import + +@class OIDEndSessionRequest; + +NS_ASSUME_NONNULL_BEGIN + +/*! @brief Represents the response to an End Session request. + @see http://openid.net/specs/openid-connect-frontchannel-1_0.html + */ + +@interface OIDEndSessionResponse : NSObject { + OIDEndSessionRequest *_request; + NSString *_state; +} + +/*! @brief The request which was serviced. + */ +@property(nonatomic, readonly) OIDEndSessionRequest *request; + +/*! @brief REQUIRED if the "state" parameter was present in the client authorization request. The + exact value received from the client. + @remarks state + */ +@property(nonatomic, readonly, nullable) NSString *state; + +/*! @internal + @brief Unavailable. Please use initWithParameters:. + */ +- (instancetype)init NS_UNAVAILABLE; + +/*! @brief Designated initializer. + @param request The serviced request. + @param parameters The decoded parameters returned from the End Session Endpoint. + @remarks Known parameters are extracted from the @c parameters parameter and the normative + properties are populated. Non-normative parameters are placed in the + @c #additionalParameters dictionary. + */ +- (instancetype)initWithRequest:(OIDEndSessionRequest *)request + parameters:(NSDictionary *> *)parameters +NS_DESIGNATED_INITIALIZER; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Source/OIDEndSessionResponse.m b/Source/OIDEndSessionResponse.m new file mode 100644 index 000000000..ce111c173 --- /dev/null +++ b/Source/OIDEndSessionResponse.m @@ -0,0 +1,84 @@ +/*! @file OIDEndSessionResponse.m + @brief AppAuth iOS SDK + @copyright + Copyright 2017 The AppAuth Authors. All Rights Reserved. + @copydetails + 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. + */ + +#import "OIDEndSessionResponse.h" + +#import "OIDEndSessionRequest.h" +#import "OIDDefines.h" + +/*! @brief The key for the @c state property in the incoming parameters and for @c NSSecureCoding. + */ +static NSString *const kStateKey = @"state"; + +/*! @brief Key used to encode the @c request property for @c NSSecureCoding + */ +static NSString *const kRequestKey = @"request"; + +@implementation OIDEndSessionResponse + +@synthesize request = _request; +@synthesize state = _state; + +#pragma mark - Initializers + +- (instancetype)init +OID_UNAVAILABLE_USE_INITIALIZER(@selector(initWithRequest:parameters:)); + +- (instancetype)initWithRequest:(OIDEndSessionRequest *)request parameters:(NSDictionary *> *)parameters +{ + self = [super init]; + if (self) { + _request = [request copy]; + _state = [parameters[kStateKey] copy]; + } + return self; +} + +#pragma mark - NSCopying + +- (instancetype)copyWithZone:(nullable NSZone *)zone { + // The documentation for NSCopying specifically advises us to return a reference to the original + // instance in the case where instances are immutable (as ours is): + // "Implement NSCopying by retaining the original instead of creating a new copy when the class + // and its contents are immutable." + return self; +} + +#pragma mark - NSSecureCoding + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + OIDEndSessionRequest *request = [aDecoder decodeObjectOfClass:[OIDEndSessionRequest class] forKey:kRequestKey]; + NSString *state = [aDecoder decodeObjectOfClass:[NSString class] forKey:kStateKey]; + + self = [self initWithRequest:request parameters:@{}]; + if (self) { + _state = state; + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:_request forKey:kRequestKey]; + [aCoder encodeObject:_state forKey:kStateKey]; +} + +@end diff --git a/Source/OIDServiceDiscovery.h b/Source/OIDServiceDiscovery.h index e3c8eda90..73721bdb6 100644 --- a/Source/OIDServiceDiscovery.h +++ b/Source/OIDServiceDiscovery.h @@ -81,6 +81,12 @@ NS_ASSUME_NONNULL_BEGIN */ @property(nonatomic, readonly, nullable) NSURL *registrationEndpoint; +/* @brief OPTIONAL. URL of the OP's RP-Initiated Logout endpoint. + @remarks end_session_endpoint + @seealso http://openid.net/specs/openid-connect-session-1_0.html#OPMetadata + */ +@property(nonatomic, readonly, nullable) NSURL *endSessionEndpoint; + /*! @brief RECOMMENDED. JSON array containing a list of the OAuth 2.0 [RFC6749] scope values that this server supports. The server MUST support the openid scope value. Servers MAY choose not to advertise some supported scope values even when this parameter is used, although those diff --git a/Source/OIDServiceDiscovery.m b/Source/OIDServiceDiscovery.m index 565010577..ce233967f 100644 --- a/Source/OIDServiceDiscovery.m +++ b/Source/OIDServiceDiscovery.m @@ -30,6 +30,7 @@ static NSString *const kUserinfoEndpointKey = @"userinfo_endpoint"; static NSString *const kJWKSURLKey = @"jwks_uri"; static NSString *const kRegistrationEndpointKey = @"registration_endpoint"; +static NSString *const kEndSessionEndpointKey = @"end_session_endpoint"; static NSString *const kScopesSupportedKey = @"scopes_supported"; static NSString *const kResponseTypesSupportedKey = @"response_types_supported"; static NSString *const kResponseModesSupportedKey = @"response_modes_supported"; @@ -223,6 +224,10 @@ - (nullable NSURL *)registrationEndpoint { return [NSURL URLWithString:_discoveryDictionary[kRegistrationEndpointKey]]; } +- (nullable NSURL *)endSessionEndpoint { + return [NSURL URLWithString:_discoveryDictionary[kEndSessionEndpointKey]]; +} + - (nullable NSArray *)scopesSupported { return _discoveryDictionary[kScopesSupportedKey]; } diff --git a/UnitTests/OIDEndSessionRequestTests.h b/UnitTests/OIDEndSessionRequestTests.h new file mode 100644 index 000000000..48f902757 --- /dev/null +++ b/UnitTests/OIDEndSessionRequestTests.h @@ -0,0 +1,31 @@ +/*! @file OIDServiceDiscoveryTests.m + @brief AppAuth iOS SDK + @copyright + Copyright 2017 The AppAuth Authors. All Rights Reserved. + @copydetails + 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. + */ + +#import + +@class OIDEndSessionRequest; + +NS_ASSUME_NONNULL_BEGIN + +@interface OIDEndSessionRequestTests : XCTestCase + ++ (OIDEndSessionRequest *)testInstance; + +@end + +NS_ASSUME_NONNULL_END diff --git a/UnitTests/OIDEndSessionRequestTests.m b/UnitTests/OIDEndSessionRequestTests.m new file mode 100644 index 000000000..4aadc6b57 --- /dev/null +++ b/UnitTests/OIDEndSessionRequestTests.m @@ -0,0 +1,124 @@ +/*! @file OIDServiceDiscoveryTests.m + @brief AppAuth iOS SDK + @copyright + Copyright 2017 The AppAuth Authors. All Rights Reserved. + @copydetails + 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. + */ + +#import "OIDEndSessionRequestTests.h" + +#import "OIDServiceDiscoveryTests.h" +#import "Source/OIDEndSessionRequest.h" +#import "Source/OIDServiceConfiguration.h" +#import "Source/OIDServiceDiscovery.h" + +/*! @brief Test value for the @c redirectURL property. + */ +static NSString *const kTestRedirectURL = @"http://www.google.com/"; + +/*! @brief Test key for the @c additionalParameters property. + */ +static NSString *const kTestAdditionalParameterKey = @"A"; + +/*! @brief Test value for the @c additionalParameters property. + */ +static NSString *const kTestAdditionalParameterValue = @"1"; + +/*! @brief Test value for the @c state property. + */ +static NSString *const kTestState = @"State"; + +/*! @brief Test value for the @c idTokenHint property. + */ +static NSString *const kTestIdTokenHint = @"id-token-hint"; + +@implementation OIDEndSessionRequestTests + ++ (OIDEndSessionRequest *)testInstance { + NSDictionary *additionalParameters = + @{ kTestAdditionalParameterKey : kTestAdditionalParameterValue }; + + OIDServiceDiscovery *discoveryDocument = [[OIDServiceDiscovery alloc] initWithDictionary:[OIDServiceDiscoveryTests completeServiceDiscoveryDictionary] error:nil]; + OIDServiceConfiguration *configuration = [[OIDServiceConfiguration alloc] initWithDiscoveryDocument:discoveryDocument]; + + return [[OIDEndSessionRequest alloc] initWithConfiguration:configuration + idTokenHint:kTestIdTokenHint + postLogoutRedirectURL:[NSURL URLWithString:kTestRedirectURL] + state:kTestState + additionalParameters:additionalParameters]; +} + +/*! @brief Tests the @c NSCopying implementation by round-tripping an instance through the copying + process and checking to make sure the source and destination instances are equivalent. + */ +- (void)testCopying { + OIDEndSessionRequest *request = [[self class] testInstance]; + + XCTAssertEqualObjects(request.idTokenHint, kTestIdTokenHint); + XCTAssertEqualObjects(request.postLogoutRedirectURL, [NSURL URLWithString:kTestRedirectURL]); + XCTAssertEqualObjects(request.state, kTestState); + XCTAssertEqualObjects(request.additionalParameters[kTestAdditionalParameterKey], + kTestAdditionalParameterValue); + + OIDEndSessionRequest *requestCopy = [request copy]; + + XCTAssertNotNil(requestCopy.configuration); + XCTAssertEqualObjects(requestCopy.configuration, request.configuration); + XCTAssertEqualObjects(requestCopy.postLogoutRedirectURL, request.postLogoutRedirectURL); + XCTAssertEqualObjects(requestCopy.state, request.state); + XCTAssertEqualObjects(requestCopy.idTokenHint, request.idTokenHint); +} + +/*! @brief Tests the @c NSSecureCoding by round-tripping an instance through the coding process and + checking to make sure the source and destination instances are equivalent. + */ +- (void)testSecureCoding { + OIDEndSessionRequest *request = [[self class] testInstance]; + + XCTAssertEqualObjects(request.idTokenHint, kTestIdTokenHint); + XCTAssertEqualObjects(request.postLogoutRedirectURL, [NSURL URLWithString:kTestRedirectURL]); + XCTAssertEqualObjects(request.state, kTestState); + XCTAssertEqualObjects(request.additionalParameters[kTestAdditionalParameterKey], + kTestAdditionalParameterValue); + + NSData *data = [NSKeyedArchiver archivedDataWithRootObject:request]; + OIDEndSessionRequest *requestCopy = [NSKeyedUnarchiver unarchiveObjectWithData:data]; + + XCTAssertNotNil(requestCopy.configuration); + XCTAssertEqualObjects(requestCopy.configuration.authorizationEndpoint, + request.configuration.authorizationEndpoint); + XCTAssertEqualObjects(requestCopy.postLogoutRedirectURL, request.postLogoutRedirectURL); + XCTAssertEqualObjects(requestCopy.state, request.state); + XCTAssertEqualObjects(requestCopy.idTokenHint, request.idTokenHint); +} + +- (void)testLogoutRequestURL { + OIDEndSessionRequest *request = [[self class] testInstance]; + NSURL *endSessionRequestURL = request.endSessionRequestURL; + + NSURLComponents *components = [NSURLComponents componentsWithString:endSessionRequestURL.absoluteString]; + + XCTAssertTrue([endSessionRequestURL.absoluteString hasPrefix:@"https://www.example.com/logout"]); + + NSMutableDictionary *query = [[NSMutableDictionary alloc] init]; + for (NSURLQueryItem *queryItem in components.queryItems) { + query[queryItem.name] = queryItem.value; + } + + XCTAssertEqualObjects(query[@"state"], kTestState); + XCTAssertEqualObjects(query[@"id_token_hint"], kTestIdTokenHint); + XCTAssertEqualObjects(query[@"post_logout_redirect_uri"], kTestRedirectURL); +} + +@end diff --git a/UnitTests/OIDServiceDiscoveryTests.m b/UnitTests/OIDServiceDiscoveryTests.m index 4352c0b9c..b80d7e638 100644 --- a/UnitTests/OIDServiceDiscoveryTests.m +++ b/UnitTests/OIDServiceDiscoveryTests.m @@ -34,6 +34,7 @@ static NSString *const kUserinfoEndpointKey = @"userinfo_endpoint"; static NSString *const kJWKSURLKey = @"jwks_uri"; static NSString *const kRegistrationEndpointKey = @"registration_endpoint"; +static NSString *const kEndSessionEndpointKey = @"end_session_endpoint"; static NSString *const kScopesSupportedKey = @"scopes_supported"; static NSString *const kResponseTypesSupportedKey = @"response_types_supported"; static NSString *const kResponseModesSupportedKey = @"response_modes_supported"; @@ -97,6 +98,7 @@ + (NSDictionary *)completeServiceDiscoveryDictionary { kUserinfoEndpointKey : @"User Info Endpoint", kJWKSURLKey : @"http://www.example.com/jwks", kRegistrationEndpointKey : @"Registration Endpoint", + kEndSessionEndpointKey : @"https://www.example.com/logout", kScopesSupportedKey : @"Scopes Supported", kResponseTypesSupportedKey : @"Response Types Supported", kResponseModesSupportedKey : @"Response Modes Supported", @@ -466,6 +468,7 @@ - (void)testField_##_field_ { TestURLFieldBackedBy(userinfoEndpoint, kUserinfoEndpointKey, kTestURL); TestURLFieldBackedBy(jwksURL, kJWKSURLKey, kTestURL); TestURLFieldBackedBy(registrationEndpoint, kRegistrationEndpointKey, kTestURL); +TestURLFieldBackedBy(endSessionEndpoint, kEndSessionEndpointKey, kTestURL); TestFieldBackedBy(scopesSupported, kScopesSupportedKey, @"Scopes Supported"); TestFieldBackedBy(responseTypesSupported, kResponseTypesSupportedKey, @"Response Types Supported"); TestFieldBackedBy(responseModesSupported, kResponseModesSupportedKey, @"Response Modes Supported"); From d8351cffefb2bdebaab311750a41881c90f96fb8 Mon Sep 17 00:00:00 2001 From: Derk Gommers Date: Thu, 8 Mar 2018 17:24:40 +0100 Subject: [PATCH 02/18] Added first version of the end session flow. --- Source/OIDEndSessionFlowSession.h | 28 ++++++ Source/OIDEndSessionFlowSession.m | 158 ++++++++++++++++++++++++++++++ Source/OIDEndSessionRequest.h | 3 +- Source/OIDEndSessionRequest.m | 8 +- 4 files changed, 194 insertions(+), 3 deletions(-) create mode 100644 Source/OIDEndSessionFlowSession.h create mode 100644 Source/OIDEndSessionFlowSession.m diff --git a/Source/OIDEndSessionFlowSession.h b/Source/OIDEndSessionFlowSession.h new file mode 100644 index 000000000..eaffbc4c3 --- /dev/null +++ b/Source/OIDEndSessionFlowSession.h @@ -0,0 +1,28 @@ +/*! @file OIDDefines.h + @brief AppAuth iOS SDK + @copyright + Copyright 2015 Google Inc. All Rights Reserved. + @copydetails + 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. + */ + +#import +#import "OIDExternalUserAgentFlowSession.h" + +@class OIDEndSessionResponse; + +typedef void (^OIDEndSessionCallback)(OIDEndSessionResponse *_Nullable endSessionResponse, NSError *_Nullable error); + +@interface OIDEndSessionFlowSession : NSObject + +@end diff --git a/Source/OIDEndSessionFlowSession.m b/Source/OIDEndSessionFlowSession.m new file mode 100644 index 000000000..0adad0fd6 --- /dev/null +++ b/Source/OIDEndSessionFlowSession.m @@ -0,0 +1,158 @@ +/*! @file OIDDefines.h + @brief AppAuth iOS SDK + @copyright + Copyright 2015 Google Inc. All Rights Reserved. + @copydetails + 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. + */ + +#import "OIDEndSessionFlowSession.h" +#import "OIDEndSessionRequest.h" +#import "OIDExternalUserAgentUICoordinator.h" +#import "OIDErrorUtilities.h" +#import "OIDDefines.h" +#import "OIDURLQueryComponent.h" +#import "OIDEndSessionResponse.h" + +@interface OIDEndSessionFlowSession() { + // private variables + OIDEndSessionRequest *_request; + id _UICoordinator; + OIDEndSessionCallback _pendingEndSessionFlowCallback; +} +@end + +@implementation OIDEndSessionFlowSession + +- (instancetype)initWithRequest:(OIDEndSessionRequest *)request { + self = [super init]; + if (self) { + _request = [request copy]; + } + return self; +} + +- (void)presentEndSessionWithCoordinator:(id)UICoordinator + callback:(OIDEndSessionCallback)endSessionFlowCallback { + _UICoordinator = UICoordinator; + _pendingEndSessionFlowCallback = endSessionFlowCallback; + BOOL authorizationFlowStarted = + [_UICoordinator presentExternalUserAgentRequest:_request session:self]; + if (!authorizationFlowStarted) { + NSError *safariError = [OIDErrorUtilities errorWithCode:OIDErrorCodeSafariOpenError + underlyingError:nil + description:@"Unable to open Safari."]; + [self didFinishWithResponse:nil error:safariError]; + } +} + +- (void)cancel { + [_UICoordinator dismissExternalUserAgentUIAnimated:YES completion:^{ + NSError *error = [OIDErrorUtilities + errorWithCode:OIDErrorCodeUserCanceledAuthorizationFlow + underlyingError:nil + description:nil]; + [self didFinishWithResponse:nil error:error]; + }]; +} + +- (BOOL)shouldHandleURL:(NSURL *)URL { + NSURL *standardizedURL = [URL standardizedURL]; + NSURL *standardizedRedirectURL = [_request.postLogoutRedirectURL standardizedURL]; + + return OIDIsEqualIncludingNil(standardizedURL.scheme, standardizedRedirectURL.scheme) && + OIDIsEqualIncludingNil(standardizedURL.user, standardizedRedirectURL.user) && + OIDIsEqualIncludingNil(standardizedURL.password, standardizedRedirectURL.password) && + OIDIsEqualIncludingNil(standardizedURL.host, standardizedRedirectURL.host) && + OIDIsEqualIncludingNil(standardizedURL.port, standardizedRedirectURL.port) && + OIDIsEqualIncludingNil(standardizedURL.path, standardizedRedirectURL.path); +} + +- (BOOL)resumeExternalUserAgentFlowWithURL:(NSURL *)URL { + // rejects URLs that don't match redirect (these may be completely unrelated to the authorization) + if (![self shouldHandleURL:URL]) { + return NO; + } + // checks for an invalid state + if (!_pendingEndSessionFlowCallback) { + [NSException raise:OIDOAuthExceptionInvalidAuthorizationFlow + format:@"%@", OIDOAuthExceptionInvalidAuthorizationFlow, nil]; + } + + OIDURLQueryComponent *query = [[OIDURLQueryComponent alloc] initWithURL:URL]; + + NSError *error; + OIDEndSessionResponse *response = nil; + + // checks for an OAuth error response as per RFC6749 Section 4.1.2.1 + if (query.dictionaryValue[OIDOAuthErrorFieldError]) { + error = [OIDErrorUtilities OAuthErrorWithDomain:OIDOAuthAuthorizationErrorDomain + OAuthResponse:query.dictionaryValue + underlyingError:nil]; + } + + // no error, should be a valid OAuth 2.0 response + if (!error) { + response = [[OIDEndSessionResponse alloc] initWithRequest:_request + parameters:query.dictionaryValue]; + + // verifies that the state in the response matches the state in the request, or both are nil + if (!OIDIsEqualIncludingNil(_request.state, response.state)) { + NSMutableDictionary *userInfo = [query.dictionaryValue mutableCopy]; + userInfo[NSLocalizedDescriptionKey] = + [NSString stringWithFormat:@"State mismatch, expecting %@ but got %@ in authorization " + "response %@", + _request.state, + response.state, + response]; + response = nil; + error = [NSError errorWithDomain:OIDOAuthAuthorizationErrorDomain + code:OIDErrorCodeOAuthAuthorizationClientError + userInfo:userInfo]; + } + } + + [_UICoordinator dismissExternalUserAgentUIAnimated:YES completion:^{ + [self didFinishWithResponse:response error:error]; + }]; + + return YES; +} + +- (void)failExternalUserAgentFlowWithError:(NSError *)error { + [self didFinishWithResponse:nil error:error]; +} + +/*! @brief Invokes the pending callback and performs cleanup. + @param response The authorization response, if any to return to the callback. + @param error The error, if any, to return to the callback. + */ +- (void)didFinishWithResponse:(nullable OIDEndSessionResponse *)response + error:(nullable NSError *)error { + OIDEndSessionCallback callback = _pendingEndSessionFlowCallback; + _pendingEndSessionFlowCallback = nil; + _UICoordinator = nil; + if (callback) { + callback(response, error); + } +} + +- (void)failAuthorizationFlowWithError:(NSError *)error { + [self failExternalUserAgentFlowWithError:error]; +} + +- (BOOL)resumeAuthorizationFlowWithURL:(NSURL *)URL { + return [self resumeExternalUserAgentFlowWithURL:URL]; +} + +@end diff --git a/Source/OIDEndSessionRequest.h b/Source/OIDEndSessionRequest.h index 08e12af9a..8d5c567b1 100644 --- a/Source/OIDEndSessionRequest.h +++ b/Source/OIDEndSessionRequest.h @@ -17,12 +17,13 @@ */ #import +#import "OIDExternalUserAgentRequest.h" @class OIDServiceConfiguration; NS_ASSUME_NONNULL_BEGIN -@interface OIDEndSessionRequest : NSObject { +@interface OIDEndSessionRequest : NSObject { OIDServiceConfiguration *_configuration; NSURL *_postLogoutRedirectURL; NSString *_idTokenHint; diff --git a/Source/OIDEndSessionRequest.m b/Source/OIDEndSessionRequest.m index f0b51767b..d839afc63 100644 --- a/Source/OIDEndSessionRequest.m +++ b/Source/OIDEndSessionRequest.m @@ -157,9 +157,9 @@ + (nullable NSString *)generateState { return [OIDTokenUtilities randomURLSafeStringWithSize:kStateSizeBytes]; } -#pragma mark - +#pragma mark - OIDExternalUserAgentRequest -- (NSURL *)endSessionRequestURL { +- (NSURL *)externalUserAgentRequestURL { OIDURLQueryComponent *query = [[OIDURLQueryComponent alloc] init]; // Add any additional parameters the client has specified. @@ -184,4 +184,8 @@ - (NSURL *)endSessionRequestURL { return [query URLByReplacingQueryInURL:_configuration.discoveryDocument.endSessionEndpoint]; } +- (NSString *)redirectScheme { + return self.postLogoutRedirectURL.scheme; +} + @end From 09e55a30d78d3fd9c9491e829cca2d35334d0926 Mon Sep 17 00:00:00 2001 From: Derk Gommers Date: Fri, 9 Mar 2018 13:44:56 +0100 Subject: [PATCH 03/18] Initiation of the iOS user agent doesn't have to be nullable. --- Source/iOS/OIDExternalUserAgentIOS.h | 2 +- Source/iOS/OIDExternalUserAgentIOS.m | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/iOS/OIDExternalUserAgentIOS.h b/Source/iOS/OIDExternalUserAgentIOS.h index 9f5ebdfff..c6c99ac0e 100644 --- a/Source/iOS/OIDExternalUserAgentIOS.h +++ b/Source/iOS/OIDExternalUserAgentIOS.h @@ -58,7 +58,7 @@ NS_ASSUME_NONNULL_BEGIN @param presentingViewController The view controller from which to present the \SFSafariViewController. */ -- (nullable instancetype)initWithPresentingViewController: +- (instancetype)initWithPresentingViewController: (UIViewController *)presentingViewController NS_DESIGNATED_INITIALIZER; diff --git a/Source/iOS/OIDExternalUserAgentIOS.m b/Source/iOS/OIDExternalUserAgentIOS.m index d87aecf07..1c4b259e5 100644 --- a/Source/iOS/OIDExternalUserAgentIOS.m +++ b/Source/iOS/OIDExternalUserAgentIOS.m @@ -67,7 +67,7 @@ + (void)setSafariViewControllerFactory:(id)facto gSafariViewControllerFactory = factory; } -- (nullable instancetype)initWithPresentingViewController: +- (instancetype)initWithPresentingViewController: (UIViewController *)presentingViewController { self = [super init]; if (self) { From ca096e50a70fa0b6113d7a5c12e71187e355d2b7 Mon Sep 17 00:00:00 2001 From: Derk Gommers Date: Fri, 9 Mar 2018 13:45:31 +0100 Subject: [PATCH 04/18] Expose the new OIDAuthorizationFlowSession file through the umbrella header. --- Source/Framework/AppAuth.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/Framework/AppAuth.h b/Source/Framework/AppAuth.h index e0c132619..006a6c030 100644 --- a/Source/Framework/AppAuth.h +++ b/Source/Framework/AppAuth.h @@ -29,6 +29,7 @@ FOUNDATION_EXPORT const unsigned char AppAuthVersionString[]; #import #import #import +#import #import #import #import From d6d1474c11a63899e1074cad63653674549e3ae4 Mon Sep 17 00:00:00 2001 From: Derk Gommers Date: Fri, 9 Mar 2018 13:47:36 +0100 Subject: [PATCH 05/18] Replaced UICoordinator with the new ExternalUserAgent protocol in the end session flow. --- Source/OIDEndSessionFlowSession.m | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Source/OIDEndSessionFlowSession.m b/Source/OIDEndSessionFlowSession.m index 0adad0fd6..11960f5ff 100644 --- a/Source/OIDEndSessionFlowSession.m +++ b/Source/OIDEndSessionFlowSession.m @@ -18,7 +18,7 @@ #import "OIDEndSessionFlowSession.h" #import "OIDEndSessionRequest.h" -#import "OIDExternalUserAgentUICoordinator.h" +#import "OIDExternalUserAgent.h" #import "OIDErrorUtilities.h" #import "OIDDefines.h" #import "OIDURLQueryComponent.h" @@ -27,7 +27,7 @@ @interface OIDEndSessionFlowSession() { // private variables OIDEndSessionRequest *_request; - id _UICoordinator; + id _externalUserAgent; OIDEndSessionCallback _pendingEndSessionFlowCallback; } @end @@ -42,12 +42,12 @@ - (instancetype)initWithRequest:(OIDEndSessionRequest *)request { return self; } -- (void)presentEndSessionWithCoordinator:(id)UICoordinator +- (void)presentEndSessionWithExternalUserAgent:(id)externalUserAgent callback:(OIDEndSessionCallback)endSessionFlowCallback { - _UICoordinator = UICoordinator; + _externalUserAgent = externalUserAgent; _pendingEndSessionFlowCallback = endSessionFlowCallback; BOOL authorizationFlowStarted = - [_UICoordinator presentExternalUserAgentRequest:_request session:self]; + [_externalUserAgent presentExternalUserAgentRequest:_request session:self]; if (!authorizationFlowStarted) { NSError *safariError = [OIDErrorUtilities errorWithCode:OIDErrorCodeSafariOpenError underlyingError:nil @@ -57,7 +57,7 @@ - (void)presentEndSessionWithCoordinator:(id) } - (void)cancel { - [_UICoordinator dismissExternalUserAgentUIAnimated:YES completion:^{ + [_externalUserAgent dismissExternalUserAgentAnimated:YES completion:^{ NSError *error = [OIDErrorUtilities errorWithCode:OIDErrorCodeUserCanceledAuthorizationFlow underlyingError:nil @@ -122,7 +122,7 @@ - (BOOL)resumeExternalUserAgentFlowWithURL:(NSURL *)URL { } } - [_UICoordinator dismissExternalUserAgentUIAnimated:YES completion:^{ + [_externalUserAgent dismissExternalUserAgentAnimated:YES completion:^{ [self didFinishWithResponse:response error:error]; }]; @@ -141,7 +141,7 @@ - (void)didFinishWithResponse:(nullable OIDEndSessionResponse *)response error:(nullable NSError *)error { OIDEndSessionCallback callback = _pendingEndSessionFlowCallback; _pendingEndSessionFlowCallback = nil; - _UICoordinator = nil; + _externalUserAgent = nil; if (callback) { callback(response, error); } From d32b07b0f10bae858df197c82a254e3ac49add67 Mon Sep 17 00:00:00 2001 From: Derk Gommers Date: Fri, 9 Mar 2018 13:47:57 +0100 Subject: [PATCH 06/18] Added public interface for end session flow session. --- Source/OIDEndSessionFlowSession.h | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/Source/OIDEndSessionFlowSession.h b/Source/OIDEndSessionFlowSession.h index eaffbc4c3..5bb4ed61b 100644 --- a/Source/OIDEndSessionFlowSession.h +++ b/Source/OIDEndSessionFlowSession.h @@ -17,12 +17,26 @@ */ #import -#import "OIDExternalUserAgentFlowSession.h" + +@protocol OIDExternalUserAgentSession; +@protocol OIDExternalUserAgent; @class OIDEndSessionResponse; +@class OIDEndSessionRequest; + +NS_ASSUME_NONNULL_BEGIN typedef void (^OIDEndSessionCallback)(OIDEndSessionResponse *_Nullable endSessionResponse, NSError *_Nullable error); -@interface OIDEndSessionFlowSession : NSObject +@interface OIDEndSessionFlowSession : NSObject + +- (instancetype)init NS_UNAVAILABLE; + +- (instancetype)initWithRequest:(OIDEndSessionRequest *)request NS_DESIGNATED_INITIALIZER; + +- (void)presentEndSessionWithExternalUserAgent:(id)externalUserAgent + callback:(OIDEndSessionCallback)endSessionFlowCallback; @end + +NS_ASSUME_NONNULL_END From e64b3894bb4f24fa209097319d14f8fdc846c3b0 Mon Sep 17 00:00:00 2001 From: Derk Gommers Date: Fri, 9 Mar 2018 13:49:35 +0100 Subject: [PATCH 07/18] endSessionRequestURL was not defined anymore as it is replaced by `externalUserAgentRequestURL`. --- Source/OIDEndSessionRequest.h | 7 ------- Source/OIDEndSessionRequest.m | 2 +- UnitTests/OIDEndSessionRequestTests.m | 2 +- 3 files changed, 2 insertions(+), 9 deletions(-) diff --git a/Source/OIDEndSessionRequest.h b/Source/OIDEndSessionRequest.h index 8d5c567b1..8ed007905 100644 --- a/Source/OIDEndSessionRequest.h +++ b/Source/OIDEndSessionRequest.h @@ -99,13 +99,6 @@ NS_ASSUME_NONNULL_BEGIN additionalParameters:(nullable NSDictionary *)additionalParameters NS_DESIGNATED_INITIALIZER; -/*! @brief Constructs the request URI by adding the request parameters to the query component of the - authorization endpoint URI using the "application/x-www-form-urlencoded" format. - @return A URL representing the authorization request. - @see http://openid.net/specs/openid-connect-session-1_0.html#RPLogout - */ -- (NSURL *)endSessionRequestURL; - @end NS_ASSUME_NONNULL_END diff --git a/Source/OIDEndSessionRequest.m b/Source/OIDEndSessionRequest.m index d839afc63..72c6bd61a 100644 --- a/Source/OIDEndSessionRequest.m +++ b/Source/OIDEndSessionRequest.m @@ -150,7 +150,7 @@ - (NSString *)description { return [NSString stringWithFormat:@"<%@: %p, request: %@>", NSStringFromClass([self class]), self, - self.endSessionRequestURL]; + self.externalUserAgentRequestURL]; } + (nullable NSString *)generateState { diff --git a/UnitTests/OIDEndSessionRequestTests.m b/UnitTests/OIDEndSessionRequestTests.m index 4aadc6b57..785fec02a 100644 --- a/UnitTests/OIDEndSessionRequestTests.m +++ b/UnitTests/OIDEndSessionRequestTests.m @@ -105,7 +105,7 @@ - (void)testSecureCoding { - (void)testLogoutRequestURL { OIDEndSessionRequest *request = [[self class] testInstance]; - NSURL *endSessionRequestURL = request.endSessionRequestURL; + NSURL *endSessionRequestURL = request.externalUserAgentRequestURL; NSURLComponents *components = [NSURLComponents componentsWithString:endSessionRequestURL.absoluteString]; From 91756b5f69a353dfe54139c021d2ae281282a4d3 Mon Sep 17 00:00:00 2001 From: Derk Gommers Date: Fri, 9 Mar 2018 13:50:21 +0100 Subject: [PATCH 08/18] The idToken can be nullable as it is an optional paramater of the end session request. --- Source/OIDEndSessionRequest.h | 4 ++-- Source/OIDEndSessionRequest.m | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Source/OIDEndSessionRequest.h b/Source/OIDEndSessionRequest.h index 8ed007905..3157a712e 100644 --- a/Source/OIDEndSessionRequest.h +++ b/Source/OIDEndSessionRequest.h @@ -79,7 +79,7 @@ NS_ASSUME_NONNULL_BEGIN */ - (instancetype) initWithConfiguration:(OIDServiceConfiguration *)configuration - idTokenHint:(NSString *)idTokenHint + idTokenHint:(nullable NSString *)idTokenHint postLogoutRedirectURL:(NSURL *)postLogoutRedirectURL additionalParameters:(nullable NSDictionary *)additionalParameters; @@ -93,7 +93,7 @@ NS_ASSUME_NONNULL_BEGIN */ - (instancetype) initWithConfiguration:(OIDServiceConfiguration *)configuration - idTokenHint:(NSString *)idTokenHint + idTokenHint:(nullable NSString *)idTokenHint postLogoutRedirectURL:(NSURL *)postLogoutRedirectURL state:(NSString *)state additionalParameters:(nullable NSDictionary *)additionalParameters diff --git a/Source/OIDEndSessionRequest.m b/Source/OIDEndSessionRequest.m index 72c6bd61a..1e7b23387 100644 --- a/Source/OIDEndSessionRequest.m +++ b/Source/OIDEndSessionRequest.m @@ -71,10 +71,10 @@ - (instancetype)init ); - (instancetype)initWithConfiguration:(OIDServiceConfiguration *)configuration - idTokenHint:(NSString *)idTokenHint + idTokenHint:(nullable NSString *)idTokenHint postLogoutRedirectURL:(NSURL *)postLogoutRedirectURL state:(NSString *)state - additionalParameters:(NSDictionary *)additionalParameters + additionalParameters:(nullable NSDictionary *)additionalParameters { self = [super init]; if (self) { @@ -89,9 +89,9 @@ - (instancetype)initWithConfiguration:(OIDServiceConfiguration *)configuration } - (instancetype)initWithConfiguration:(OIDServiceConfiguration *)configuration - idTokenHint:(NSString *)idTokenHint + idTokenHint:(nullable NSString *)idTokenHint postLogoutRedirectURL:(NSURL *)postLogoutRedirectURL - additionalParameters:(NSDictionary *)additionalParameters + additionalParameters:(nullable NSDictionary *)additionalParameters { return [self initWithConfiguration:configuration idTokenHint:idTokenHint From 2d8e80d98deee6aa9f6f46ad177f93a300b59385 Mon Sep 17 00:00:00 2001 From: Derk Gommers Date: Fri, 9 Mar 2018 14:15:19 +0100 Subject: [PATCH 09/18] Added OIDEndSessionFlowSession to the Xcode project targets. --- AppAuth.xcodeproj/project.pbxproj | 63 ++++++++++++++++++++++--------- 1 file changed, 45 insertions(+), 18 deletions(-) diff --git a/AppAuth.xcodeproj/project.pbxproj b/AppAuth.xcodeproj/project.pbxproj index 6f43a410b..eb21c6f2b 100644 --- a/AppAuth.xcodeproj/project.pbxproj +++ b/AppAuth.xcodeproj/project.pbxproj @@ -377,21 +377,6 @@ A6339DAB20321AE50043D1C9 /* OIDAuthorizationFlowSession.h in Headers */ = {isa = PBXBuildFile; fileRef = A6339DA3203211320043D1C9 /* OIDAuthorizationFlowSession.h */; settings = {ATTRIBUTES = (Public, ); }; }; A6339DAC20321AE70043D1C9 /* OIDAuthorizationFlowSession.h in Headers */ = {isa = PBXBuildFile; fileRef = A6339DA3203211320043D1C9 /* OIDAuthorizationFlowSession.h */; settings = {ATTRIBUTES = (Public, ); }; }; A6339DAD20321AEB0043D1C9 /* OIDAuthorizationFlowSession.h in Headers */ = {isa = PBXBuildFile; fileRef = A6339DA3203211320043D1C9 /* OIDAuthorizationFlowSession.h */; settings = {ATTRIBUTES = (Public, ); }; }; - A6DEAB9B2018E4AD0022AC32 /* OIDExternalUserAgent.h in Headers */ = {isa = PBXBuildFile; fileRef = A6DEAB982018E4A20022AC32 /* OIDExternalUserAgent.h */; settings = {ATTRIBUTES = (Public, ); }; }; - A6DEAB9C2018E4AD0022AC32 /* OIDExternalUserAgent.h in Headers */ = {isa = PBXBuildFile; fileRef = A6DEAB982018E4A20022AC32 /* OIDExternalUserAgent.h */; settings = {ATTRIBUTES = (Public, ); }; }; - A6DEAB9D2018E4AD0022AC32 /* OIDExternalUserAgent.h in Headers */ = {isa = PBXBuildFile; fileRef = A6DEAB982018E4A20022AC32 /* OIDExternalUserAgent.h */; settings = {ATTRIBUTES = (Public, ); }; }; - A6DEAB9E2018E4AE0022AC32 /* OIDExternalUserAgent.h in Headers */ = {isa = PBXBuildFile; fileRef = A6DEAB982018E4A20022AC32 /* OIDExternalUserAgent.h */; }; - A6DEAB9F2018E4B00022AC32 /* OIDExternalUserAgentRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = A6DEAB9A2018E4A20022AC32 /* OIDExternalUserAgentRequest.h */; settings = {ATTRIBUTES = (Public, ); }; }; - A6DEABA02018E4B00022AC32 /* OIDExternalUserAgentRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = A6DEAB9A2018E4A20022AC32 /* OIDExternalUserAgentRequest.h */; settings = {ATTRIBUTES = (Public, ); }; }; - A6DEABA22018E4B60022AC32 /* OIDExternalUserAgentRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = A6DEAB9A2018E4A20022AC32 /* OIDExternalUserAgentRequest.h */; settings = {ATTRIBUTES = (Public, ); }; }; - A6DEABA32018E4B70022AC32 /* OIDExternalUserAgentRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = A6DEAB9A2018E4A20022AC32 /* OIDExternalUserAgentRequest.h */; settings = {ATTRIBUTES = (Public, ); }; }; - A6DEABA42018E4B90022AC32 /* OIDExternalUserAgentSession.h in Headers */ = {isa = PBXBuildFile; fileRef = A6DEAB992018E4A20022AC32 /* OIDExternalUserAgentSession.h */; settings = {ATTRIBUTES = (Public, ); }; }; - A6DEABA52018E4BA0022AC32 /* OIDExternalUserAgentSession.h in Headers */ = {isa = PBXBuildFile; fileRef = A6DEAB992018E4A20022AC32 /* OIDExternalUserAgentSession.h */; settings = {ATTRIBUTES = (Public, ); }; }; - A6DEABA62018E4BA0022AC32 /* OIDExternalUserAgentSession.h in Headers */ = {isa = PBXBuildFile; fileRef = A6DEAB992018E4A20022AC32 /* OIDExternalUserAgentSession.h */; settings = {ATTRIBUTES = (Public, ); }; }; - A6DEABA72018E4BA0022AC32 /* OIDExternalUserAgentSession.h in Headers */ = {isa = PBXBuildFile; fileRef = A6DEAB992018E4A20022AC32 /* OIDExternalUserAgentSession.h */; settings = {ATTRIBUTES = (Public, ); }; }; - A6DEABAA2018E5B50022AC32 /* OIDExternalUserAgentIOS.m in Sources */ = {isa = PBXBuildFile; fileRef = A6DEABA82018E5B50022AC32 /* OIDExternalUserAgentIOS.m */; }; - A6DEABAB2018E5C50022AC32 /* OIDExternalUserAgentIOS.h in Headers */ = {isa = PBXBuildFile; fileRef = A6DEABA92018E5B50022AC32 /* OIDExternalUserAgentIOS.h */; settings = {ATTRIBUTES = (Public, ); }; }; - A6DEABAF2018E5D80022AC32 /* OIDExternalUserAgentIOS.m in Sources */ = {isa = PBXBuildFile; fileRef = A6DEABA82018E5B50022AC32 /* OIDExternalUserAgentIOS.m */; }; A6CEB11A2007E49C009D492A /* OIDEndSessionRequestTests.m in Sources */ = {isa = PBXBuildFile; fileRef = A6CEB1182007E384009D492A /* OIDEndSessionRequestTests.m */; }; A6CEB11B2007E49D009D492A /* OIDEndSessionRequestTests.m in Sources */ = {isa = PBXBuildFile; fileRef = A6CEB1182007E384009D492A /* OIDEndSessionRequestTests.m */; }; A6CEB11C2007E49E009D492A /* OIDEndSessionRequestTests.m in Sources */ = {isa = PBXBuildFile; fileRef = A6CEB1182007E384009D492A /* OIDEndSessionRequestTests.m */; }; @@ -409,6 +394,21 @@ A6DEAB8B2017A7160022AC32 /* OIDEndSessionRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = CF37C06C1F1FC21A00662E41 /* OIDEndSessionRequest.m */; }; A6DEAB8C2017A7160022AC32 /* OIDEndSessionRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = CF37C06C1F1FC21A00662E41 /* OIDEndSessionRequest.m */; }; A6DEAB8D2017A7170022AC32 /* OIDEndSessionRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = CF37C06C1F1FC21A00662E41 /* OIDEndSessionRequest.m */; }; + A6DEAB9B2018E4AD0022AC32 /* OIDExternalUserAgent.h in Headers */ = {isa = PBXBuildFile; fileRef = A6DEAB982018E4A20022AC32 /* OIDExternalUserAgent.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A6DEAB9C2018E4AD0022AC32 /* OIDExternalUserAgent.h in Headers */ = {isa = PBXBuildFile; fileRef = A6DEAB982018E4A20022AC32 /* OIDExternalUserAgent.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A6DEAB9D2018E4AD0022AC32 /* OIDExternalUserAgent.h in Headers */ = {isa = PBXBuildFile; fileRef = A6DEAB982018E4A20022AC32 /* OIDExternalUserAgent.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A6DEAB9E2018E4AE0022AC32 /* OIDExternalUserAgent.h in Headers */ = {isa = PBXBuildFile; fileRef = A6DEAB982018E4A20022AC32 /* OIDExternalUserAgent.h */; }; + A6DEAB9F2018E4B00022AC32 /* OIDExternalUserAgentRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = A6DEAB9A2018E4A20022AC32 /* OIDExternalUserAgentRequest.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A6DEABA02018E4B00022AC32 /* OIDExternalUserAgentRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = A6DEAB9A2018E4A20022AC32 /* OIDExternalUserAgentRequest.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A6DEABA22018E4B60022AC32 /* OIDExternalUserAgentRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = A6DEAB9A2018E4A20022AC32 /* OIDExternalUserAgentRequest.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A6DEABA32018E4B70022AC32 /* OIDExternalUserAgentRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = A6DEAB9A2018E4A20022AC32 /* OIDExternalUserAgentRequest.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A6DEABA42018E4B90022AC32 /* OIDExternalUserAgentSession.h in Headers */ = {isa = PBXBuildFile; fileRef = A6DEAB992018E4A20022AC32 /* OIDExternalUserAgentSession.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A6DEABA52018E4BA0022AC32 /* OIDExternalUserAgentSession.h in Headers */ = {isa = PBXBuildFile; fileRef = A6DEAB992018E4A20022AC32 /* OIDExternalUserAgentSession.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A6DEABA62018E4BA0022AC32 /* OIDExternalUserAgentSession.h in Headers */ = {isa = PBXBuildFile; fileRef = A6DEAB992018E4A20022AC32 /* OIDExternalUserAgentSession.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A6DEABA72018E4BA0022AC32 /* OIDExternalUserAgentSession.h in Headers */ = {isa = PBXBuildFile; fileRef = A6DEAB992018E4A20022AC32 /* OIDExternalUserAgentSession.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A6DEABAA2018E5B50022AC32 /* OIDExternalUserAgentIOS.m in Sources */ = {isa = PBXBuildFile; fileRef = A6DEABA82018E5B50022AC32 /* OIDExternalUserAgentIOS.m */; }; + A6DEABAB2018E5C50022AC32 /* OIDExternalUserAgentIOS.h in Headers */ = {isa = PBXBuildFile; fileRef = A6DEABA92018E5B50022AC32 /* OIDExternalUserAgentIOS.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A6DEABAF2018E5D80022AC32 /* OIDExternalUserAgentIOS.m in Sources */ = {isa = PBXBuildFile; fileRef = A6DEABA82018E5B50022AC32 /* OIDExternalUserAgentIOS.m */; }; A6DEABB02018ECE80022AC32 /* OIDEndSessionRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = CF37C06B1F1FC21A00662E41 /* OIDEndSessionRequest.h */; settings = {ATTRIBUTES = (Public, ); }; }; A6DEABB12018ECE80022AC32 /* OIDEndSessionRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = CF37C06B1F1FC21A00662E41 /* OIDEndSessionRequest.h */; settings = {ATTRIBUTES = (Public, ); }; }; A6DEABB22018ECE90022AC32 /* OIDEndSessionRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = CF37C06B1F1FC21A00662E41 /* OIDEndSessionRequest.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -417,6 +417,18 @@ A6DEABB52018ECF30022AC32 /* OIDEndSessionResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = CF6431F21F228A980075B6B5 /* OIDEndSessionResponse.h */; settings = {ATTRIBUTES = (Public, ); }; }; A6DEABB62018ECF30022AC32 /* OIDEndSessionResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = CF6431F21F228A980075B6B5 /* OIDEndSessionResponse.h */; settings = {ATTRIBUTES = (Public, ); }; }; A6DEABB72018ECF40022AC32 /* OIDEndSessionResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = CF6431F21F228A980075B6B5 /* OIDEndSessionResponse.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B39FA9C22052C02B00BD9778 /* OIDEndSessionFlowSession.h in Headers */ = {isa = PBXBuildFile; fileRef = B39FA9C12052C02700BD9778 /* OIDEndSessionFlowSession.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B39FA9C42052C02D00BD9778 /* OIDEndSessionFlowSession.h in Headers */ = {isa = PBXBuildFile; fileRef = B39FA9C12052C02700BD9778 /* OIDEndSessionFlowSession.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B39FA9C52052C02E00BD9778 /* OIDEndSessionFlowSession.h in Headers */ = {isa = PBXBuildFile; fileRef = B39FA9C12052C02700BD9778 /* OIDEndSessionFlowSession.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B39FA9C62052C02E00BD9778 /* OIDEndSessionFlowSession.h in Headers */ = {isa = PBXBuildFile; fileRef = B39FA9C12052C02700BD9778 /* OIDEndSessionFlowSession.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B39FA9C72052C03900BD9778 /* OIDEndSessionFlowSession.m in Sources */ = {isa = PBXBuildFile; fileRef = B39FA9C02052C02700BD9778 /* OIDEndSessionFlowSession.m */; }; + B39FA9C82052C03A00BD9778 /* OIDEndSessionFlowSession.m in Sources */ = {isa = PBXBuildFile; fileRef = B39FA9C02052C02700BD9778 /* OIDEndSessionFlowSession.m */; }; + B39FA9C92052C03A00BD9778 /* OIDEndSessionFlowSession.m in Sources */ = {isa = PBXBuildFile; fileRef = B39FA9C02052C02700BD9778 /* OIDEndSessionFlowSession.m */; }; + B39FA9CA2052C03B00BD9778 /* OIDEndSessionFlowSession.m in Sources */ = {isa = PBXBuildFile; fileRef = B39FA9C02052C02700BD9778 /* OIDEndSessionFlowSession.m */; }; + B39FA9CB2052C03C00BD9778 /* OIDEndSessionFlowSession.m in Sources */ = {isa = PBXBuildFile; fileRef = B39FA9C02052C02700BD9778 /* OIDEndSessionFlowSession.m */; }; + B39FA9CC2052C03D00BD9778 /* OIDEndSessionFlowSession.m in Sources */ = {isa = PBXBuildFile; fileRef = B39FA9C02052C02700BD9778 /* OIDEndSessionFlowSession.m */; }; + B39FA9CD2052C03D00BD9778 /* OIDEndSessionFlowSession.m in Sources */ = {isa = PBXBuildFile; fileRef = B39FA9C02052C02700BD9778 /* OIDEndSessionFlowSession.m */; }; + B39FA9CE2052C03E00BD9778 /* OIDEndSessionFlowSession.m in Sources */ = {isa = PBXBuildFile; fileRef = B39FA9C02052C02700BD9778 /* OIDEndSessionFlowSession.m */; }; CF37C06E1F1FC21A00662E41 /* OIDEndSessionRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = CF37C06C1F1FC21A00662E41 /* OIDEndSessionRequest.m */; }; CF37C06F1F1FC21A00662E41 /* OIDEndSessionRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = CF37C06C1F1FC21A00662E41 /* OIDEndSessionRequest.m */; }; CF37C0701F1FC21A00662E41 /* OIDEndSessionRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = CF37C06C1F1FC21A00662E41 /* OIDEndSessionRequest.m */; }; @@ -605,18 +617,19 @@ 60140F841DE43C8C00DA0DC3 /* OIDRegistrationResponseTests.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OIDRegistrationResponseTests.h; sourceTree = ""; }; 60140F851DE43CC700DA0DC3 /* OIDRegistrationResponseTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OIDRegistrationResponseTests.m; sourceTree = ""; }; A6339DA3203211320043D1C9 /* OIDAuthorizationFlowSession.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OIDAuthorizationFlowSession.h; sourceTree = ""; }; + A6CEB1172007E384009D492A /* OIDEndSessionRequestTests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OIDEndSessionRequestTests.h; sourceTree = ""; }; + A6CEB1182007E384009D492A /* OIDEndSessionRequestTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OIDEndSessionRequestTests.m; sourceTree = ""; }; A6DEAB982018E4A20022AC32 /* OIDExternalUserAgent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OIDExternalUserAgent.h; sourceTree = ""; }; A6DEAB992018E4A20022AC32 /* OIDExternalUserAgentSession.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OIDExternalUserAgentSession.h; sourceTree = ""; }; A6DEAB9A2018E4A20022AC32 /* OIDExternalUserAgentRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OIDExternalUserAgentRequest.h; sourceTree = ""; }; A6DEABA82018E5B50022AC32 /* OIDExternalUserAgentIOS.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OIDExternalUserAgentIOS.m; path = iOS/OIDExternalUserAgentIOS.m; sourceTree = ""; }; A6DEABA92018E5B50022AC32 /* OIDExternalUserAgentIOS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OIDExternalUserAgentIOS.h; path = iOS/OIDExternalUserAgentIOS.h; sourceTree = ""; }; - A6CEB1172007E384009D492A /* OIDEndSessionRequestTests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OIDEndSessionRequestTests.h; sourceTree = ""; }; - A6CEB1182007E384009D492A /* OIDEndSessionRequestTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OIDEndSessionRequestTests.m; sourceTree = ""; }; + B39FA9C02052C02700BD9778 /* OIDEndSessionFlowSession.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OIDEndSessionFlowSession.m; sourceTree = ""; }; + B39FA9C12052C02700BD9778 /* OIDEndSessionFlowSession.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OIDEndSessionFlowSession.h; sourceTree = ""; }; CF37C06B1F1FC21A00662E41 /* OIDEndSessionRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OIDEndSessionRequest.h; sourceTree = ""; }; CF37C06C1F1FC21A00662E41 /* OIDEndSessionRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OIDEndSessionRequest.m; sourceTree = ""; }; CF6431F21F228A980075B6B5 /* OIDEndSessionResponse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OIDEndSessionResponse.h; sourceTree = ""; }; CF6431F31F228A980075B6B5 /* OIDEndSessionResponse.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OIDEndSessionResponse.m; sourceTree = ""; }; - F68103B61D2568D10053658E /* OIDAuthorizationUICoordinator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OIDAuthorizationUICoordinator.h; sourceTree = ""; }; F6F60FB01D2BFEFE00325CB3 /* OIDAuthState+IOS.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "OIDAuthState+IOS.m"; path = "iOS/OIDAuthState+IOS.m"; sourceTree = ""; }; F6F60FB11D2BFEFE00325CB3 /* OIDAuthorizationService+IOS.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "OIDAuthorizationService+IOS.m"; path = "iOS/OIDAuthorizationService+IOS.m"; sourceTree = ""; }; F6F60FB31D2BFEFE00325CB3 /* OIDAuthorizationService+IOS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "OIDAuthorizationService+IOS.h"; path = "iOS/OIDAuthorizationService+IOS.h"; sourceTree = ""; }; @@ -810,6 +823,8 @@ A6DEAB982018E4A20022AC32 /* OIDExternalUserAgent.h */, 341741C31C5D8243000EF209 /* OIDFieldMapping.h */, 341741C41C5D8243000EF209 /* OIDFieldMapping.m */, + B39FA9C12052C02700BD9778 /* OIDEndSessionFlowSession.h */, + B39FA9C02052C02700BD9778 /* OIDEndSessionFlowSession.m */, CF6431F21F228A980075B6B5 /* OIDEndSessionResponse.h */, CF6431F31F228A980075B6B5 /* OIDEndSessionResponse.m */, CF37C06B1F1FC21A00662E41 /* OIDEndSessionRequest.h */, @@ -951,6 +966,7 @@ 343AAAF81E83499000F9D36E /* OIDTokenResponse.h in Headers */, A6DEABB42018ECF20022AC32 /* OIDEndSessionResponse.h in Headers */, 343AAAF61E83499000F9D36E /* OIDServiceDiscovery.h in Headers */, + B39FA9C22052C02B00BD9778 /* OIDEndSessionFlowSession.h in Headers */, 343AAAF11E83499000F9D36E /* OIDGrantTypes.h in Headers */, 343AAA6D1E83466B00F9D36E /* OIDAuthState+IOS.h in Headers */, 343AAAEF1E83499000F9D36E /* OIDRegistrationResponse.h in Headers */, @@ -990,6 +1006,7 @@ 343AAB111E83499100F9D36E /* OIDTokenUtilities.h in Headers */, 343AAB0A1E83499100F9D36E /* OIDResponseTypes.h in Headers */, A6DEAB9C2018E4AD0022AC32 /* OIDExternalUserAgent.h in Headers */, + B39FA9C42052C02D00BD9778 /* OIDEndSessionFlowSession.h in Headers */, 343AAB0B1E83499100F9D36E /* OIDScopes.h in Headers */, 343AAB9B1E834A8800F9D36E /* AppAuth.h in Headers */, A6DEABB12018ECE80022AC32 /* OIDEndSessionRequest.h in Headers */, @@ -1023,6 +1040,7 @@ 343AAB291E83499200F9D36E /* OIDTokenUtilities.h in Headers */, 343AAB221E83499200F9D36E /* OIDResponseTypes.h in Headers */, A6DEAB9D2018E4AD0022AC32 /* OIDExternalUserAgent.h in Headers */, + B39FA9C52052C02E00BD9778 /* OIDEndSessionFlowSession.h in Headers */, 343AAB231E83499200F9D36E /* OIDScopes.h in Headers */, 343AAB9C1E834A8900F9D36E /* AppAuth.h in Headers */, A6DEABB22018ECE90022AC32 /* OIDEndSessionRequest.h in Headers */, @@ -1045,6 +1063,7 @@ 343AAB9D1E834A8A00F9D36E /* AppAuth.h in Headers */, A6DEABA72018E4BA0022AC32 /* OIDExternalUserAgentSession.h in Headers */, 343AAADF1E83494400F9D36E /* OIDExternalUserAgentMac.h in Headers */, + B39FA9C62052C02E00BD9778 /* OIDEndSessionFlowSession.h in Headers */, 343AAAE01E83494400F9D36E /* OIDAuthState+Mac.h in Headers */, 343AAADD1E83494400F9D36E /* OIDRedirectHTTPHandler.h in Headers */, 343AAB3C1E83499200F9D36E /* OIDScopeUtilities.h in Headers */, @@ -1503,6 +1522,7 @@ 341310C21E6F944B00D5DEE5 /* OIDError.m in Sources */, 341310BE1E6F943C00D5DEE5 /* OIDClientMetadataParameters.m in Sources */, 34FEA6AF1DB6E083005C9212 /* OIDLoopbackHTTPServer.m in Sources */, + B39FA9C82052C03A00BD9778 /* OIDEndSessionFlowSession.m in Sources */, 341310C61E6F944B00D5DEE5 /* OIDRegistrationRequest.m in Sources */, 340DAEBC1D582AF100EC285B /* OIDRedirectHTTPHandler.m in Sources */, 340DAE5D1D5821AB00EC285B /* OIDAuthState.m in Sources */, @@ -1547,6 +1567,7 @@ 341741E51C5D8243000EF209 /* OIDScopeUtilities.m in Sources */, 341741DC1C5D8243000EF209 /* OIDAuthorizationResponse.m in Sources */, 341741E61C5D8243000EF209 /* OIDServiceConfiguration.m in Sources */, + B39FA9C72052C03900BD9778 /* OIDEndSessionFlowSession.m in Sources */, 60140F7A1DE4276800DA0DC3 /* OIDClientMetadataParameters.m in Sources */, 341741DE1C5D8243000EF209 /* OIDAuthState.m in Sources */, CF37C06E1F1FC21A00662E41 /* OIDEndSessionRequest.m in Sources */, @@ -1635,6 +1656,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + B39FA9C92052C03A00BD9778 /* OIDEndSessionFlowSession.m in Sources */, 341310DA1E6F944D00D5DEE5 /* OIDScopes.m in Sources */, 341310D51E6F944D00D5DEE5 /* OIDFieldMapping.m in Sources */, 341E709B1DE18796004353C1 /* OIDAuthState.m in Sources */, @@ -1677,6 +1699,7 @@ 343AAA831E83478900F9D36E /* OIDAuthorizationService.m in Sources */, 343AAA851E83478900F9D36E /* OIDClientMetadataParameters.m in Sources */, 343AAA931E83478900F9D36E /* OIDTokenUtilities.m in Sources */, + B39FA9CB2052C03C00BD9778 /* OIDEndSessionFlowSession.m in Sources */, 343AAA901E83478900F9D36E /* OIDServiceDiscovery.m in Sources */, 343AAA911E83478900F9D36E /* OIDTokenRequest.m in Sources */, 345AE748202D526900738D22 /* OIDExternalUserAgentIOSCustomBrowser.m in Sources */, @@ -1721,6 +1744,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + B39FA9CC2052C03D00BD9778 /* OIDEndSessionFlowSession.m in Sources */, 343AAB771E8349B000F9D36E /* OIDScopes.m in Sources */, 343AAB721E8349B000F9D36E /* OIDFieldMapping.m in Sources */, 343AAB6E1E8349B000F9D36E /* OIDAuthState.m in Sources */, @@ -1751,6 +1775,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + B39FA9CD2052C03D00BD9778 /* OIDEndSessionFlowSession.m in Sources */, 343AAB631E8349B000F9D36E /* OIDScopes.m in Sources */, 343AAB5E1E8349B000F9D36E /* OIDFieldMapping.m in Sources */, 343AAB5A1E8349B000F9D36E /* OIDAuthState.m in Sources */, @@ -1806,6 +1831,7 @@ 343AAB481E8349AF00F9D36E /* OIDError.m in Sources */, 343AAADC1E83493D00F9D36E /* OIDAuthState+Mac.m in Sources */, 343AAADA1E83493D00F9D36E /* OIDAuthorizationService+Mac.m in Sources */, + B39FA9CE2052C03E00BD9778 /* OIDEndSessionFlowSession.m in Sources */, 343AAB4C1E8349AF00F9D36E /* OIDRegistrationRequest.m in Sources */, A6DEAB8D2017A7170022AC32 /* OIDEndSessionRequest.m in Sources */, 343AAB451E8349AF00F9D36E /* OIDAuthorizationService.m in Sources */, @@ -1860,6 +1886,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + B39FA9CA2052C03B00BD9778 /* OIDEndSessionFlowSession.m in Sources */, 3474240B1E7F4BA000D3E6D6 /* OIDScopes.m in Sources */, 347424061E7F4BA000D3E6D6 /* OIDFieldMapping.m in Sources */, 347424021E7F4BA000D3E6D6 /* OIDAuthState.m in Sources */, From 6113d482fda4e3e5312d82a0fb38042c577e3e66 Mon Sep 17 00:00:00 2001 From: Derk Gommers Date: Fri, 9 Mar 2018 14:15:48 +0100 Subject: [PATCH 10/18] Match copyright statement with other files. --- Source/OIDEndSessionFlowSession.h | 4 ++-- Source/OIDEndSessionFlowSession.m | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Source/OIDEndSessionFlowSession.h b/Source/OIDEndSessionFlowSession.h index 5bb4ed61b..d803374aa 100644 --- a/Source/OIDEndSessionFlowSession.h +++ b/Source/OIDEndSessionFlowSession.h @@ -1,7 +1,7 @@ -/*! @file OIDDefines.h +/*! @file OIDEndSessionFlowSession.h @brief AppAuth iOS SDK @copyright - Copyright 2015 Google Inc. All Rights Reserved. + Copyright 2018 The AppAuth Authors. All Rights Reserved. @copydetails Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/Source/OIDEndSessionFlowSession.m b/Source/OIDEndSessionFlowSession.m index 11960f5ff..d18624f8c 100644 --- a/Source/OIDEndSessionFlowSession.m +++ b/Source/OIDEndSessionFlowSession.m @@ -1,7 +1,7 @@ -/*! @file OIDDefines.h +/*! @file OIDEndSessionFlowSession.m @brief AppAuth iOS SDK @copyright - Copyright 2015 Google Inc. All Rights Reserved. + Copyright 2018 The AppAuth Authors. All Rights Reserved. @copydetails Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -17,6 +17,7 @@ */ #import "OIDEndSessionFlowSession.h" + #import "OIDEndSessionRequest.h" #import "OIDExternalUserAgent.h" #import "OIDErrorUtilities.h" From 6f8b41beb444fa2f096a24e0b411b10e62c544b3 Mon Sep 17 00:00:00 2001 From: Derk Gommers Date: Fri, 9 Mar 2018 14:16:51 +0100 Subject: [PATCH 11/18] Asume NONNULL inside flow session implementation, matching to other files. --- Source/OIDEndSessionFlowSession.m | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Source/OIDEndSessionFlowSession.m b/Source/OIDEndSessionFlowSession.m index d18624f8c..3e085eddb 100644 --- a/Source/OIDEndSessionFlowSession.m +++ b/Source/OIDEndSessionFlowSession.m @@ -25,6 +25,8 @@ #import "OIDURLQueryComponent.h" #import "OIDEndSessionResponse.h" +NS_ASSUME_NONNULL_BEGIN + @interface OIDEndSessionFlowSession() { // private variables OIDEndSessionRequest *_request; @@ -157,3 +159,5 @@ - (BOOL)resumeAuthorizationFlowWithURL:(NSURL *)URL { } @end + +NS_ASSUME_NONNULL_END From 7f696da663f4bfe9765215851ccb4e30d8838505 Mon Sep 17 00:00:00 2001 From: Derk Gommers Date: Fri, 9 Mar 2018 14:18:12 +0100 Subject: [PATCH 12/18] Alphabetic order of imports. --- Source/OIDEndSessionFlowSession.h | 4 ++-- Source/OIDEndSessionFlowSession.m | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Source/OIDEndSessionFlowSession.h b/Source/OIDEndSessionFlowSession.h index d803374aa..cdc3a834b 100644 --- a/Source/OIDEndSessionFlowSession.h +++ b/Source/OIDEndSessionFlowSession.h @@ -18,11 +18,11 @@ #import -@protocol OIDExternalUserAgentSession; @protocol OIDExternalUserAgent; +@protocol OIDExternalUserAgentSession; -@class OIDEndSessionResponse; @class OIDEndSessionRequest; +@class OIDEndSessionResponse; NS_ASSUME_NONNULL_BEGIN diff --git a/Source/OIDEndSessionFlowSession.m b/Source/OIDEndSessionFlowSession.m index 3e085eddb..c8732cc63 100644 --- a/Source/OIDEndSessionFlowSession.m +++ b/Source/OIDEndSessionFlowSession.m @@ -18,12 +18,12 @@ #import "OIDEndSessionFlowSession.h" +#import "OIDDefines.h" #import "OIDEndSessionRequest.h" -#import "OIDExternalUserAgent.h" +#import "OIDEndSessionResponse.h" #import "OIDErrorUtilities.h" -#import "OIDDefines.h" +#import "OIDExternalUserAgent.h" #import "OIDURLQueryComponent.h" -#import "OIDEndSessionResponse.h" NS_ASSUME_NONNULL_BEGIN From fd15bc7c82f07538ebb0885f72daf8f32c2f733b Mon Sep 17 00:00:00 2001 From: Derk Gommers Date: Fri, 9 Mar 2018 15:00:43 +0100 Subject: [PATCH 13/18] Added method to invoke end session flow from the AuthState. --- Source/OIDAuthState.h | 26 +++++++++++++++++++++++++- Source/OIDAuthState.m | 20 ++++++++++++++++++++ Source/OIDEndSessionFlowSession.h | 4 +--- 3 files changed, 46 insertions(+), 4 deletions(-) diff --git a/Source/OIDAuthState.h b/Source/OIDAuthState.h index 3a98d378a..80a44fd0a 100644 --- a/Source/OIDAuthState.h +++ b/Source/OIDAuthState.h @@ -20,6 +20,8 @@ @class OIDAuthorizationRequest; @class OIDAuthorizationResponse; @class OIDAuthState; +@class OIDEndSessionRequest; +@class OIDEndSessionResponse; @class OIDRegistrationResponse; @class OIDTokenResponse; @class OIDTokenRequest; @@ -41,7 +43,7 @@ typedef void (^OIDAuthStateAction)(NSString *_Nullable accessToken, NSError *_Nullable error); /*! @brief The method called when the @c - OIDAuthState.authStateByPresentingAuthorizationRequest:presentingViewController:callback: + OIDAuthState.authStateByPresentingAuthorizationRequest:externalUserAgent:callback: method has completed or failed. @param authState The auth state, if the authorization request succeeded. @param error The error if an error occurred. @@ -49,6 +51,15 @@ typedef void (^OIDAuthStateAction)(NSString *_Nullable accessToken, typedef void (^OIDAuthStateAuthorizationCallback)(OIDAuthState *_Nullable authState, NSError *_Nullable error); +/*! @brief The method called when the @c OIDAuthState.presentEndSessionRequest:externalUserAgent:(id)externalUserAgent + callback has completed or failed. + method has completed or failed. + @param endSessionResponse The response to the end session request from the OP. + @param error The error if an error occurred. + */ +typedef void (^OIDEndSessionCallback)(OIDEndSessionResponse *_Nullable endSessionResponse, + NSError *_Nullable error); + /*! @brief A convenience class that retains the auth state between @c OIDAuthorizationResponse%s and @c OIDTokenResponse%s. */ @@ -284,6 +295,19 @@ typedef void (^OIDAuthStateAuthorizationCallback)(OIDAuthState *_Nullable authSt - (void)withFreshTokensPerformAction:(OIDAuthStateAction)action __deprecated_msg("Use OIDAuthState.performActionWithFreshTokens:"); + +/*! @brief Presents a RP-initiated logout using the external user agent. + @param endSessionRequest The end session request to present. + @param externalUserAgent A external user agent that can present an external user-agent request. + @param callback The method called when the request has completed or failed. + @return A @c OIDExternalUserAgentSession instance which will terminate when it + receives a @c OIDExternalUserAgentSession.cancel message, or after processing a @c OIDExternalUserAgentSession.resumeExternalUserAgentFlowWithURL: message. + @see http://openid.net/specs/openid-connect-session-1_0.html#RPLogout + */ +- (id)presentEndSessionRequest:(OIDEndSessionRequest *)endSessionRequest + externalUserAgent:(id)externalUserAgent + callback:(OIDEndSessionCallback)callback; + @end NS_ASSUME_NONNULL_END diff --git a/Source/OIDAuthState.m b/Source/OIDAuthState.m index 06a515d44..c939dfc0b 100644 --- a/Source/OIDAuthState.m +++ b/Source/OIDAuthState.m @@ -24,8 +24,11 @@ #import "OIDAuthorizationResponse.h" #import "OIDAuthorizationService.h" #import "OIDDefines.h" +#import "OIDEndSessionFlowSession.h" +#import "OIDEndSessionRequest.h" #import "OIDError.h" #import "OIDErrorUtilities.h" +#import "OIDExternalUserAgent.h" #import "OIDRegistrationResponse.h" #import "OIDTokenRequest.h" #import "OIDTokenResponse.h" @@ -532,6 +535,23 @@ - (BOOL)isTokenFresh { return tokenFresh; } +#pragma mark - End session + +- (id)presentEndSessionRequest:(OIDEndSessionRequest *)endSessionRequest + externalUserAgent:(id)externalUserAgent + callback:(OIDEndSessionCallback)callback { + OIDEndSessionFlowSession *session = [[OIDEndSessionFlowSession alloc] initWithRequest:endSessionRequest]; + OIDEndSessionCallback wrappedCallback = ^(OIDEndSessionResponse *_Nullable endSessionResponse, + NSError *_Nullable error) { + callback(endSessionResponse, error); + }; + + // presents the end session request + [session presentEndSessionWithExternalUserAgent:externalUserAgent callback:wrappedCallback]; + + return session; +} + @end diff --git a/Source/OIDEndSessionFlowSession.h b/Source/OIDEndSessionFlowSession.h index cdc3a834b..6c070a709 100644 --- a/Source/OIDEndSessionFlowSession.h +++ b/Source/OIDEndSessionFlowSession.h @@ -16,7 +16,7 @@ limitations under the License. */ -#import +#import "OIDAuthState.h" @protocol OIDExternalUserAgent; @protocol OIDExternalUserAgentSession; @@ -26,8 +26,6 @@ NS_ASSUME_NONNULL_BEGIN -typedef void (^OIDEndSessionCallback)(OIDEndSessionResponse *_Nullable endSessionResponse, NSError *_Nullable error); - @interface OIDEndSessionFlowSession : NSObject - (instancetype)init NS_UNAVAILABLE; From ff969d63c58f0e2bde07416c7d1db525cee2ae00 Mon Sep 17 00:00:00 2001 From: Derk Gommers Date: Fri, 9 Mar 2018 16:01:59 +0100 Subject: [PATCH 14/18] Added documentation to the new header. --- Source/OIDEndSessionFlowSession.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Source/OIDEndSessionFlowSession.h b/Source/OIDEndSessionFlowSession.h index 6c070a709..375e7fb51 100644 --- a/Source/OIDEndSessionFlowSession.h +++ b/Source/OIDEndSessionFlowSession.h @@ -26,12 +26,25 @@ NS_ASSUME_NONNULL_BEGIN +/*! @brief Flow handler for the @c OIDEndSessionRequest + @see http://openid.net/specs/openid-connect-session-1_0.html#RPLogout + */ @interface OIDEndSessionFlowSession : NSObject +/*! @internal + @brief Unavailable. Please use @c initWithRequest:. + */ - (instancetype)init NS_UNAVAILABLE; +/*! @brief Create new end session flow + @param request The end session request + */ - (instancetype)initWithRequest:(OIDEndSessionRequest *)request NS_DESIGNATED_INITIALIZER; +/*! @brief Present the sesion request on the provided @c OIDExternalUserAgent. + @param externalUserAgent The user agent for presenting the request. + @param callback The callback that will be triggered after the session is completed. + */ - (void)presentEndSessionWithExternalUserAgent:(id)externalUserAgent callback:(OIDEndSessionCallback)endSessionFlowCallback; From ac5edf3791a91026196d551023c2782a029ee82e Mon Sep 17 00:00:00 2001 From: Derk Gommers Date: Fri, 9 Mar 2018 16:14:31 +0100 Subject: [PATCH 15/18] Invalidate the state when RP initiated logout was successful. --- Source/OIDAuthState.h | 1 + Source/OIDAuthState.m | 11 ++++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/Source/OIDAuthState.h b/Source/OIDAuthState.h index 80a44fd0a..7cec5dec3 100644 --- a/Source/OIDAuthState.h +++ b/Source/OIDAuthState.h @@ -297,6 +297,7 @@ typedef void (^OIDEndSessionCallback)(OIDEndSessionResponse *_Nullable endSessio /*! @brief Presents a RP-initiated logout using the external user agent. + @remarks Invalidates the @c OIDAuthState on successful logout. @param endSessionRequest The end session request to present. @param externalUserAgent A external user agent that can present an external user-agent request. @param callback The method called when the request has completed or failed. diff --git a/Source/OIDAuthState.m b/Source/OIDAuthState.m index c939dfc0b..a9b59d61c 100644 --- a/Source/OIDAuthState.m +++ b/Source/OIDAuthState.m @@ -313,12 +313,16 @@ - (BOOL)isAuthorized { - (void)updateWithRegistrationResponse:(OIDRegistrationResponse *)registrationResponse { _lastRegistrationResponse = registrationResponse; + [self resetState]; + [self didChangeState]; +} + +- (void)resetState { _refreshToken = nil; _scope = nil; _lastAuthorizationResponse = nil; _lastTokenResponse = nil; _authorizationError = nil; - [self didChangeState]; } - (void)updateWithAuthorizationResponse:(nullable OIDAuthorizationResponse *)authorizationResponse @@ -543,6 +547,11 @@ - (BOOL)isTokenFresh { OIDEndSessionFlowSession *session = [[OIDEndSessionFlowSession alloc] initWithRequest:endSessionRequest]; OIDEndSessionCallback wrappedCallback = ^(OIDEndSessionResponse *_Nullable endSessionResponse, NSError *_Nullable error) { + if (!error) { + [self resetState]; + [self didChangeState]; + } + callback(endSessionResponse, error); }; From 033229525c84d1dc41e7850ab4188e156e7cc3f8 Mon Sep 17 00:00:00 2001 From: Derk Gommers Date: Tue, 13 Mar 2018 15:14:40 +0100 Subject: [PATCH 16/18] Present end session request category for iOS external user agent. --- Source/iOS/OIDAuthState+IOS.h | 16 ++++++++++++++++ Source/iOS/OIDAuthState+IOS.m | 10 ++++++++++ 2 files changed, 26 insertions(+) diff --git a/Source/iOS/OIDAuthState+IOS.h b/Source/iOS/OIDAuthState+IOS.h index 3ebc9b028..265d3db07 100644 --- a/Source/iOS/OIDAuthState+IOS.h +++ b/Source/iOS/OIDAuthState+IOS.h @@ -41,6 +41,22 @@ NS_ASSUME_NONNULL_BEGIN presentingViewController:(UIViewController *)presentingViewController callback:(OIDAuthStateAuthorizationCallback)callback; +/*! @brief Presents a RP-initiated logout using the external user agent. + @param endSessionRequest The end session request to present. + @param presentingViewController The view controller from which to present external user agent. + @param callback The method called when the request has completed or failed. + @return A @c OIDExternalUserAgentSession instance which will terminate when it receives a + @c OIDExternalUserAgentSession.cancel message, or after processing a + @c OIDExternalUserAgentSession.resumeExternalUserAgentFlowWithURL: message. + @discussion Afer a successful ending of the session, it invalidates the @c OIDAuthState. + Remove references to this instance. Hence, a new authorization flow is required + to retrieve a new instance of @c OIDAuthState. + @see http://openid.net/specs/openid-connect-session-1_0.html#RPLogout +*/ +- (id)presentEndSessionRequest:(OIDEndSessionRequest *)endSessionRequest + presentingViewController:(UIViewController *)presentingViewController + callback:(OIDEndSessionCallback)callback; + @end NS_ASSUME_NONNULL_END diff --git a/Source/iOS/OIDAuthState+IOS.m b/Source/iOS/OIDAuthState+IOS.m index 37f614021..4cae18fe5 100644 --- a/Source/iOS/OIDAuthState+IOS.m +++ b/Source/iOS/OIDAuthState+IOS.m @@ -34,4 +34,14 @@ @implementation OIDAuthState (IOS) callback:callback]; } +- (id)presentEndSessionRequest:(OIDEndSessionRequest *)endSessionRequest + presentingViewController:(UIViewController *)presentingViewController + callback:(OIDEndSessionCallback)callback { + OIDExternalUserAgentIOS *externalUserAgent = [[OIDExternalUserAgentIOS alloc] + initWithPresentingViewController:presentingViewController]; + return [self presentEndSessionRequest:endSessionRequest + externalUserAgent:externalUserAgent + callback:callback]; +} + @end From dcb8a15f81af68416edde634fa0370a7c9932a83 Mon Sep 17 00:00:00 2001 From: Derk Gommers Date: Tue, 13 Mar 2018 15:14:48 +0100 Subject: [PATCH 17/18] Present end session request category for Mac external user agent. --- Source/macOS/OIDAuthState+Mac.h | 15 +++++++++++++++ Source/macOS/OIDAuthState+Mac.m | 8 ++++++++ 2 files changed, 23 insertions(+) diff --git a/Source/macOS/OIDAuthState+Mac.h b/Source/macOS/OIDAuthState+Mac.h index 7de9f7324..c3276e7cb 100644 --- a/Source/macOS/OIDAuthState+Mac.h +++ b/Source/macOS/OIDAuthState+Mac.h @@ -35,6 +35,21 @@ NS_ASSUME_NONNULL_BEGIN + (id) authStateByPresentingAuthorizationRequest:(OIDAuthorizationRequest *)authorizationRequest callback:(OIDAuthStateAuthorizationCallback)callback; + +/*! @brief Presents a RP-initiated logout using the external user agent. + @param endSessionRequest The end session request to present. + @param callback The method called when the request has completed or failed. + @return A @c OIDExternalUserAgentSession instance which will terminate when it receives a + @c OIDExternalUserAgentSession.cancel message, or after processing a + @c OIDExternalUserAgentSession.resumeExternalUserAgentFlowWithURL: message. + @discussion Afer a successful ending of the session, it invalidates the @c OIDAuthState. + Remove references to this instance. Hence, a new authorization flow is required + to retrieve a new instance of @c OIDAuthState. + @see http://openid.net/specs/openid-connect-session-1_0.html#RPLogout + */ +- (id)presentEndSessionRequest:(OIDEndSessionRequest *)endSessionRequest + callback:(OIDEndSessionCallback)callback; + @end NS_ASSUME_NONNULL_END diff --git a/Source/macOS/OIDAuthState+Mac.m b/Source/macOS/OIDAuthState+Mac.m index 7b99e734f..08980cdbc 100644 --- a/Source/macOS/OIDAuthState+Mac.m +++ b/Source/macOS/OIDAuthState+Mac.m @@ -31,4 +31,12 @@ @implementation OIDAuthState (Mac) callback:callback]; } +- (id)presentEndSessionRequest:(OIDEndSessionRequest *)endSessionRequest + callback:(OIDEndSessionCallback)callback { + OIDExternalUserAgentMac *externalUserAgent = [[OIDExternalUserAgentMac alloc] init]; + return [self presentEndSessionRequest:endSessionRequest + externaluserAgent:externalUserAgent + callback:callback]; +} + @end From b9b6eac25e70b69fbf8fab2fb8550bf2043ee2c8 Mon Sep 17 00:00:00 2001 From: Derk Gommers Date: Tue, 13 Mar 2018 15:15:02 +0100 Subject: [PATCH 18/18] Some comment formatting. --- Source/OIDAuthState.h | 21 ++++++++++++--------- Source/OIDEndSessionFlowSession.h | 2 +- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/Source/OIDAuthState.h b/Source/OIDAuthState.h index 7cec5dec3..e00e64253 100644 --- a/Source/OIDAuthState.h +++ b/Source/OIDAuthState.h @@ -297,17 +297,20 @@ typedef void (^OIDEndSessionCallback)(OIDEndSessionResponse *_Nullable endSessio /*! @brief Presents a RP-initiated logout using the external user agent. - @remarks Invalidates the @c OIDAuthState on successful logout. - @param endSessionRequest The end session request to present. - @param externalUserAgent A external user agent that can present an external user-agent request. - @param callback The method called when the request has completed or failed. - @return A @c OIDExternalUserAgentSession instance which will terminate when it - receives a @c OIDExternalUserAgentSession.cancel message, or after processing a @c OIDExternalUserAgentSession.resumeExternalUserAgentFlowWithURL: message. - @see http://openid.net/specs/openid-connect-session-1_0.html#RPLogout + @param endSessionRequest The end session request to present. + @param externalUserAgent A external user agent that can present an external user-agent request. + @param callback The method called when the request has completed or failed. + @return A @c OIDExternalUserAgentSession instance which will terminate when it receives a + @c OIDExternalUserAgentSession.cancel message, or after processing a + @c OIDExternalUserAgentSession.resumeExternalUserAgentFlowWithURL: message. + @discussion Afer a successful ending of the session, it invalidates the @c OIDAuthState. + Remove references to this instance. Hence, a new authorization flow is required + to retrieve a new instance of @c OIDAuthState. R + @see http://openid.net/specs/openid-connect-session-1_0.html#RPLogout */ - (id)presentEndSessionRequest:(OIDEndSessionRequest *)endSessionRequest - externalUserAgent:(id)externalUserAgent - callback:(OIDEndSessionCallback)callback; + externalUserAgent:(id)externalUserAgent + callback:(OIDEndSessionCallback)callback; @end diff --git a/Source/OIDEndSessionFlowSession.h b/Source/OIDEndSessionFlowSession.h index 375e7fb51..d7750ae5a 100644 --- a/Source/OIDEndSessionFlowSession.h +++ b/Source/OIDEndSessionFlowSession.h @@ -43,7 +43,7 @@ NS_ASSUME_NONNULL_BEGIN /*! @brief Present the sesion request on the provided @c OIDExternalUserAgent. @param externalUserAgent The user agent for presenting the request. - @param callback The callback that will be triggered after the session is completed. + @param endSessionFlowCallback The callback that will be triggered after the session is completed. */ - (void)presentEndSessionWithExternalUserAgent:(id)externalUserAgent callback:(OIDEndSessionCallback)endSessionFlowCallback;