diff --git a/Sources/AppAuthCore/OIDAuthorizationService.m b/Sources/AppAuthCore/OIDAuthorizationService.m index cc749a3f9..728215859 100644 --- a/Sources/AppAuthCore/OIDAuthorizationService.m +++ b/Sources/AppAuthCore/OIDAuthorizationService.m @@ -563,6 +563,16 @@ + (void)performTokenRequest:(OIDTokenRequest *)request // OpenID Connect Core Section 3.1.3.7. rule #2 // Validates that the issuer in the ID Token matches that of the discovery document. NSURL *issuer = tokenResponse.request.configuration.issuer; + if (issuer && [issuer.path containsString:@"{tenantid}"]) { + // The Azure AD discovery document's "issuer" value contains the special placeholder + // "{tenantid}". This needs to be replaced with the actual tenant ID of the authenticated + // user, from the "tid" claim of the ID token, before validation. + NSString *tid = idToken.claims[@"tid"]; + if (tid) { + issuer = [NSURL URLWithString:[NSString stringWithFormat:@"%@://%@%@", issuer.scheme, issuer.host, + [issuer.path stringByReplacingOccurrencesOfString:@"{tenantid}" withString:tid]]]; + } + } if (issuer && ![idToken.issuer isEqual:issuer]) { NSError *invalidIDToken = [OIDErrorUtilities errorWithCode:OIDErrorCodeIDTokenFailedValidationError diff --git a/Sources/AppAuthCore/OIDServiceDiscovery.m b/Sources/AppAuthCore/OIDServiceDiscovery.m index 4d96f9db3..70813f8db 100644 --- a/Sources/AppAuthCore/OIDServiceDiscovery.m +++ b/Sources/AppAuthCore/OIDServiceDiscovery.m @@ -106,6 +106,16 @@ - (nullable instancetype)initWithJSONData:(NSData *)serviceDiscoveryJSONData return nil; } + NSString *issuer = (NSString *) json[@"issuer"]; + if (issuer && [issuer containsString:@"{tenantid}"]) { + // The Azure AD discovery document's "issuer" value contains the special placeholder + // "{tenantid}". '{' and '}' are invalid characters in URLs and have to be URL encoded before + // the issuer URL can be parsed by NSURL. + NSMutableDictionary *newJson = [NSMutableDictionary dictionaryWithDictionary:json]; + newJson[@"issuer"] = [issuer stringByReplacingOccurrencesOfString:@"{tenantid}" withString:@"%7Btenantid%7D"]; + json = newJson; + } + return [self initWithDictionary:json error:error]; }