Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move authority migration to common core #130

Merged
merged 71 commits into from
Sep 1, 2018
Merged

Conversation

antrix1989
Copy link
Contributor

No description provided.

@antrix1989 antrix1989 changed the base branch from sedemche/network_request to dev May 8, 2018 21:39
@@ -108,3 +107,17 @@
NSString *const MSID_LEGACY_TOKEN_CACHE_TYPE = @"legacysingleresourcetoken";
NSString *const MSID_ID_TOKEN_CACHE_TYPE = @"idtoken";
NSString *const MSID_GENERAL_TOKEN_CACHE_TYPE = @"token";

NSString *MSID_OAUTH2_AUTHORIZE_SUFFIX(void)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we move it out of constants?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the approach, but with Olga in this one, lets move it

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

NSParameterAssert(authority);

NSMutableDictionary *parameters = [NSMutableDictionary new];
parameters[@"api-version"] = @"1.1";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: can this be configurable?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done


NSMutableDictionary *parameters = [NSMutableDictionary new];
parameters[@"api-version"] = @"1.1";
__auto_type authorizationEndpoint = [authority.absoluteString.lowercaseString stringByAppendingString:MSID_OAUTH2_AUTHORIZE_SUFFIX()];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we need to hardcode this one?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

return nil;
}

__auto_type endpoint = (NSString *)jsonObject[@"IdentityProviderService"][@"PassiveAuthEndpoint"];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we make sure it's coming as NSString?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

else if (type == MSIDADFSTypeCloud)
{
return [NSURL URLWithString:
[NSString stringWithFormat:@"https://enterpriseregistration.windows.net/%@/enrollmentserver/contract", domain.lowercaseString]];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does this have to be a hardcoded URL?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

moved it out

}

// B2C
if ([self isB2CInstanceURL:authority])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

consider adding a separate class for normalization and additional authority manipulations. e.g. separate for B2C, ADFS etc

return NO;
}

if (authority.pathComponents.count < 2)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

again, this is realistic for AAD, but for other authorities there might be less than 2 components, because there's no tenant. Can we make sure we separate the "base" implementation from AAD specific things.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i agree with possible need for a specific aad check.
However, for check is for all authorities afaik. b2c will have "tfp" as a component, adfs => "adfs" and aad will have it's value.


#import <Foundation/Foundation.h>

@interface MSIDAuthorityCacheRecord : NSObject
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just curious, what is this class for?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is used for saving authority validation info into the cache. We use MSIDAuthorityCacheRecord & MSIDAadAuthorityCacheRecord.

context:(id<MSIDRequestContext>)context
completionBlock:(MSIDAuthorityInfoBlock)completionBlock
{
if (validate && ![MSIDAuthority isKnownHost:authority])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does this mean if authority validation is enabled for B2C, MSAL always fails?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is correct. Not supported.


@interface MSIDOpenIdProviderMetadata : NSObject

@property (nonatomic) NSURL *authorizationEndpoint;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we have additional fields from the protocol in here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can add additional fields, but we don't use them right now.

Copy link
Contributor

@unpluggedk unpluggedk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Set of nitpicks in this review,
Will do a logic review shortly.


#import <Foundation/Foundation.h>

@interface MSIDConfiguration : NSObject
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remember we've moved request params to be a configuration.
Please rename this class.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@@ -108,3 +107,17 @@
NSString *const MSID_LEGACY_TOKEN_CACHE_TYPE = @"legacysingleresourcetoken";
NSString *const MSID_ID_TOKEN_CACHE_TYPE = @"idtoken";
NSString *const MSID_GENERAL_TOKEN_CACHE_TYPE = @"token";

NSString *MSID_OAUTH2_AUTHORIZE_SUFFIX(void)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the approach, but with Olga in this one, lets move it

{
__auto_type apiVersion = MSIDConfiguration.defaultConfiguration.aadApiVersion;

return [NSString stringWithFormat:@"/oauth2/%@%@authorize", apiVersion ?: @"", apiVersion ? @"/" : @""];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ternary within a ternary is a hard read.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed

{
__auto_type apiVersion = MSIDConfiguration.defaultConfiguration.aadApiVersion;

return [NSString stringWithFormat:@"/oauth2/%@%@token", apiVersion ?: @"", apiVersion ? @"/" : @""];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above


@end

@interface MSIDAADGetAuthorityMetadataRequest : MSIDHttpRequest
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Lets remove "Get" from the name

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@interface MSIDDRSDiscoveryRequest : MSIDHttpRequest

- (instancetype)initWithDomain:(NSString *)domain
adfsType:(MSIDADFSType)adfsType NS_DESIGNATED_INITIALIZER;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: alignment

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

NSString *oauthError = jsonObject[@"error"];
if (![NSString msidIsStringNilOrBlank:oauthError])
{
if (error) *error = MSIDCreateError(MSIDErrorDomain,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: this could use a bracket and new lines :p

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

self = [super init];
if (self)
{
NSParameterAssert(domain);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you are asserting this, might as well put nonnull at method declaration

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

_parameters = parameters;

NSMutableURLRequest *urlRequest = [NSMutableURLRequest new];
urlRequest.URL = [NSURL URLWithString:[NSString stringWithFormat:@"https://%@/.well-known/webfinger", issuer.host]];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes it is afaik

@@ -42,4 +54,24 @@
+ (NSURL *)cacheUrlForAuthority:(NSURL *)authority
tenantId:(NSString *)tenantId;

+ (void)discoverAuthority:(NSURL *)authority
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

discovery is a part of the process, not the overall definition of what we need to do.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

context:(id<MSIDRequestContext>)context
completionBlock:(MSIDOpenIdConfigurationInfoBlock)completionBlock;

+ (NSURL *)normalizeAuthority:(NSURL *)authority
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why accept URL not string as a parameter here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We use authority as NSURL everywhere in common core. In my opinion, in order to be consistent, we should use it as NSURL here as well.

context:(id<MSIDRequestContext>)context
error:(NSError * __autoreleasing *)error;

+ (BOOL)isAuthorityFormatValid:(NSURL *)authority
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does this serve that normalizeAuthority doesn't? i.e./ does this need to be exposed outside of this class?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed it's declaration from public header.

@interface MSIDAuthority : NSObject

@property (class, readonly) NSCache *openIdConfigurationCache;

+ (BOOL)isADFSInstance:(NSString *)endpoint;
+ (BOOL)isADFSInstanceURL:(NSURL *)endpointUrl;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seem very duplicative of one another. do we really need these two methods?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One accepting NSURL should be enough here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These methods weren't added in this pr, I suggest to refactor them during our MSIDAuthority refactoring.

@@ -137,4 +197,145 @@ + (NSURL *)cacheUrlForAuthority:(NSURL *)authority
return [NSURL URLWithString:[NSString stringWithFormat:@"https://%@/%@", [authority msidHostWithPortIfNecessary], tenantId]];
}

+ (void)discoverAuthority:(NSURL *)authority
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

again, discovery is not what we are solely doing here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

}];
}

+ (NSURL *)normalizeAuthority:(NSURL *)authority
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as mentioned before, having this authority as a string would be better for our use case, no?

}
return NO;
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also check against login.windows.net, which is not deprecated. Advise to use login.microsoftonline.com instead

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

return NO;
}

if (authority.pathComponents.count < 2)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i agree with possible need for a specific aad check.
However, for check is for all authorities afaik. b2c will have "tfp" as a component, adfs => "adfs" and aad will have it's value.

{
if (error)
{
*error = MSIDCreateError(MSIDErrorDomain, MSIDErrorInternal, @"authority must specify a tenant or common.", nil, nil, nil, context.correlationId, nil);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MSAL also says the same, but we might want to rename this as tenant/common is pretty much AAD only.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed

context:(id<MSIDRequestContext>)context
completionBlock:(MSIDAuthorityInfoBlock)completionBlock
{
if (validate && ![MSIDAuthority isKnownHost:authority])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is correct. Not supported.

@@ -3518,6 +3724,9 @@
isa = XCBuildConfiguration;
baseConfigurationReference = D6CF4E961FC3626A00CD70C5 /* identitycore__tests__ios.xcconfig */;
buildSettings = {
CLANG_ENABLE_MODULES = YES;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
SWIFT_VERSION = 3.0;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why did we add this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed

GCC_OPTIMIZATION_LEVEL = 0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 3.0;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we use swift 3 :)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed

#import <Foundation/Foundation.h>
#import "MSIDADFSType.h"

@protocol MSIDAADEndpointProviding <NSObject>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: endpoint providing should apply also to basic Oauth2 flow, not only to AAD (e.g. we should be able to find an authorize endpoint or openid config for Google). We can take this as a separate issue though.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added comment about it in #211

@property (class, nonnull) MSIDURLSessionManager *defaultManager;
@property (nonatomic, readonly, nonnull) NSURLSessionConfiguration *configuration;
@property (nonatomic, readonly, nonnull) NSURLSession *session;
@property (nonatomic, readonly, nullable) MSIDURLSessionDelegate *delegate;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Why do we need to save delegate outside of passing it to NSURLSession?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you are right, removed it.

NSError *jsonError;
NSDictionary *jsonObject = [super responseObjectForResponse:httpResponse data:data context:context error:&jsonError];

if (jsonError)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be more accurate to check if (!jsonObject) here and return early if it's nil.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

NSURLComponents *urlComponents = [NSURLComponents componentsWithURL:mutableRequest.URL resolvingAgainstBaseURL:NO];
NSMutableDictionary *urlParameters = [[mutableRequest.URL msidQueryParameters] mutableCopy] ?: [NSMutableDictionary new];
[urlParameters addEntriesFromDictionary:parameters];
urlComponents.percentEncodedQuery = [urlParameters msidURLFormEncode];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for fixing this!

ofField:(NSString *)field
context:(id <MSIDRequestContext>)context
errorCode:(NSInteger)errorCode
error:(NSError **)error;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: remove ;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

nil, nil, context.correlationId, nil);
}

MSID_LOG_ERROR_PII(nil, @"%@", message);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think field name needs to be PII

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

__auto_type drsCloudRequest = [[MSIDDRSDiscoveryRequest alloc] initWithDomain:domain adfsType:MSIDADFSTypeCloud context:context];
[drsCloudRequest sendWithBlock:^(id response, NSError *error)
{
if (completionBlock) completionBlock(response, error);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for fixing this

@"key3": @"value3"};

NSError *error;
BOOL result = [inputDictionary assertType:NSString.class ofField:@"key1" context:nil errorCode:1 error:&error];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: please also check that correct error was returned.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@antrix1989 antrix1989 merged commit 81d2269 into dev Sep 1, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants