Skip to content

Commit

Permalink
Merge pull request #100 from WilliamDenniss/client-auth
Browse files Browse the repository at this point in the history
Support for Basic Client Authentication
  • Loading branch information
WilliamDenniss authored Mar 25, 2017
2 parents 1a20517 + 147fdc8 commit 294b992
Show file tree
Hide file tree
Showing 6 changed files with 105 additions and 15 deletions.
38 changes: 26 additions & 12 deletions Source/OIDTokenRequest.m
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ - (NSURL *)tokenRequestURL {
@return The data to pass to the token request URL.
@see https://tools.ietf.org/html/rfc6749#section-4.1.3
*/
- (NSData *)tokenRequestBody {
- (OIDURLQueryComponent *)tokenRequestBody {
OIDURLQueryComponent *query = [[OIDURLQueryComponent alloc] init];

// Add parameters, as applicable.
Expand All @@ -229,12 +229,6 @@ - (NSData *)tokenRequestBody {
if (_scope) {
[query addParameter:kScopeKey value:_scope];
}
if (_clientID) {
[query addParameter:kClientIDKey value:_clientID];
}
if (_clientSecret) {
[query addParameter:kClientSecretKey value:_clientSecret];
}
if (_redirectURL) {
[query addParameter:kRedirectURLKey value:_redirectURL.absoluteString];
}
Expand All @@ -251,10 +245,7 @@ - (NSData *)tokenRequestBody {
// Add any additional parameters the client has specified.
[query addParameters:_additionalParameters];

// Construct the body string:
NSString *bodyString = [query URLEncodedParameters];
NSData *body = [bodyString dataUsingEncoding:NSUTF8StringEncoding];
return body;
return query;
}

- (NSURLRequest *)URLRequest {
Expand All @@ -267,7 +258,30 @@ - (NSURLRequest *)URLRequest {
NSMutableURLRequest *URLRequest = [[NSURLRequest requestWithURL:tokenRequestURL] mutableCopy];
URLRequest.HTTPMethod = kHTTPPost;
[URLRequest setValue:kHTTPContentTypeHeaderValue forHTTPHeaderField:kHTTPContentTypeHeaderKey];
URLRequest.HTTPBody = [self tokenRequestBody];

OIDURLQueryComponent *bodyParameters = [self tokenRequestBody];
NSMutableDictionary *httpHeaders = [[NSMutableDictionary alloc] init];

if (_clientSecret) {
NSString *credentials = [NSString stringWithFormat:@"%@:%@", _clientID, _clientSecret];
NSData *plainData = [credentials dataUsingEncoding:NSUTF8StringEncoding];
NSString *basicAuth = [plainData base64EncodedStringWithOptions:kNilOptions];

NSString *authValue = [NSString stringWithFormat:@"Basic %@", basicAuth];
[httpHeaders setObject:authValue forKey:@"Authorization"];
} else {
[bodyParameters addParameter:kClientIDKey value:_clientID];
}

// Constructs request with the body string and headers.
NSString *bodyString = [bodyParameters URLEncodedParameters];
NSData *body = [bodyString dataUsingEncoding:NSUTF8StringEncoding];
URLRequest.HTTPBody = body;

for (id header in httpHeaders) {
[URLRequest setValue:httpHeaders[header] forHTTPHeaderField:header];
}

return URLRequest;
}

Expand Down
5 changes: 5 additions & 0 deletions UnitTests/OIDAuthorizationRequestTests.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ NS_ASSUME_NONNULL_BEGIN
*/
+ (OIDAuthorizationRequest *)testInstanceCodeFlow;

/*! @brief Creates a new @c OIDAuthorizationRequest testing a code flow request
with client authentication.
*/
+ (OIDAuthorizationRequest *)testInstanceCodeFlowClientAuth;

@end

NS_ASSUME_NONNULL_END
21 changes: 19 additions & 2 deletions UnitTests/OIDAuthorizationRequestTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ + (OIDAuthorizationRequest *)testInstance {
[[OIDAuthorizationRequest alloc] initWithConfiguration:configuration
clientId:kTestClientID
clientSecret:kTestClientSecret
scope:[OIDScopeUtilities scopesWithArray:@[ kTestScope, kTestScopeA ]]
scope:[OIDScopeUtilities scopesWithArray:@[ kTestScope, kTestScopeA ]]
redirectURL:[NSURL URLWithString:kTestRedirectURL]
responseType:kTestResponseType
state:kTestState
Expand All @@ -150,12 +150,29 @@ + (OIDAuthorizationRequest *)testInstance {
}

+ (OIDAuthorizationRequest *)testInstanceCodeFlow {
OIDServiceConfiguration *configuration = [OIDServiceConfigurationTests testInstance];
OIDAuthorizationRequest *request =
[[OIDAuthorizationRequest alloc] initWithConfiguration:configuration
clientId:kTestClientID
clientSecret:nil
scope:[OIDScopeUtilities scopesWithArray:@[ kTestScope, kTestScopeA ]]
redirectURL:[NSURL URLWithString:kTestRedirectURL]
responseType:OIDResponseTypeCode
state:kTestState
codeVerifier:kTestCodeVerifier
codeChallenge:[[self class] codeChallenge]
codeChallengeMethod:[[self class] codeChallengeMethod]
additionalParameters:nil];
return request;
}

+ (OIDAuthorizationRequest *)testInstanceCodeFlowClientAuth {
OIDServiceConfiguration *configuration = [OIDServiceConfigurationTests testInstance];
OIDAuthorizationRequest *request =
[[OIDAuthorizationRequest alloc] initWithConfiguration:configuration
clientId:kTestClientID
clientSecret:kTestClientSecret
scope:[OIDScopeUtilities scopesWithArray:@[ kTestScope, kTestScopeA ]]
scope:[OIDScopeUtilities scopesWithArray:@[ kTestScope, kTestScopeA ]]
redirectURL:[NSURL URLWithString:kTestRedirectURL]
responseType:OIDResponseTypeCode
state:kTestState
Expand Down
5 changes: 5 additions & 0 deletions UnitTests/OIDAuthorizationResponseTests.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ NS_ASSUME_NONNULL_BEGIN
*/
+ (OIDAuthorizationResponse *)testInstanceCodeFlow;

/*! @brief Creates a new @c OIDAuthorizationResponse with client authentication for testing the
code flow.
*/
+ (OIDAuthorizationResponse *)testInstanceCodeFlowClientAuth;

@end

NS_ASSUME_NONNULL_END
13 changes: 13 additions & 0 deletions UnitTests/OIDAuthorizationResponseTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,19 @@ + (OIDAuthorizationResponse *)testInstanceCodeFlow {
return response;
}

+ (OIDAuthorizationResponse *)testInstanceCodeFlowClientAuth {
OIDAuthorizationRequest *request = [OIDAuthorizationRequestTests testInstanceCodeFlowClientAuth];
OIDAuthorizationResponse *response =
[[OIDAuthorizationResponse alloc] initWithRequest:request parameters:@{
@"code" : kTestAuthorizationCode,
@"code_verifier" : kTestAuthorizationCodeVerifier,
@"state" : kTestState,
@"token_type" : OIDGrantTypeAuthorizationCode,
kTestAdditionalParameterKey : kTestAdditionalParameterValue
}];
return response;
}

/*! @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.
*/
Expand Down
38 changes: 37 additions & 1 deletion UnitTests/OIDTokenRequestTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,27 @@ + (OIDTokenRequest *)testInstance {
}

+ (OIDTokenRequest *)testInstanceCodeExchange {
OIDAuthorizationResponse *authResponse = [OIDAuthorizationResponseTests testInstance];
OIDAuthorizationResponse *authResponse = [OIDAuthorizationResponseTests testInstanceCodeFlow];
NSArray<NSString *> *scopesArray =
[OIDScopeUtilities scopesArrayWithString:authResponse.request.scope];
NSDictionary *additionalParameters =
@{ kTestAdditionalParameterKey : kTestAdditionalParameterValue };
OIDTokenRequest *request =
[[OIDTokenRequest alloc] initWithConfiguration:authResponse.request.configuration
grantType:OIDGrantTypeAuthorizationCode
authorizationCode:authResponse.authorizationCode
redirectURL:authResponse.request.redirectURL
clientID:authResponse.request.clientID
clientSecret:authResponse.request.clientSecret
scopes:scopesArray
refreshToken:kRefreshTokenTestValue
codeVerifier:authResponse.request.codeVerifier
additionalParameters:additionalParameters];
return request;
}

+ (OIDTokenRequest *)testInstanceCodeExchangeClientAuth {
OIDAuthorizationResponse *authResponse = [OIDAuthorizationResponseTests testInstanceCodeFlowClientAuth];
NSArray<NSString *> *scopesArray =
[OIDScopeUtilities scopesArrayWithString:authResponse.request.scope];
NSDictionary *additionalParameters =
Expand Down Expand Up @@ -185,4 +205,20 @@ - (void)testSecureCoding {
kTestAdditionalParameterValue);
}

- (void)testURLRequestNoClientAuth {
OIDTokenRequest *request = [[self class] testInstanceCodeExchange];
NSURLRequest *urlRequest = [request URLRequest];

id authorization = [urlRequest.allHTTPHeaderFields objectForKey:@"Authorization"];
XCTAssertNil(authorization);
}

- (void)testURLRequestBasicClientAuth {
OIDTokenRequest *request = [[self class] testInstanceCodeExchangeClientAuth];
NSURLRequest* urlRequest = [request URLRequest];

id authorization = [urlRequest.allHTTPHeaderFields objectForKey:@"Authorization"];
XCTAssertNotNil(authorization);
}

@end

0 comments on commit 294b992

Please sign in to comment.