Skip to content

Commit

Permalink
Add support for an initial access token to registration endpoint
Browse files Browse the repository at this point in the history
As per the specification, the AS may require an access token for
access to the registration endpoint - allow the app to specify this.

Specification:

https://openid.net/specs/openid-connect-registration-1_0.html#ClientRegistration

which says:

"The OpenID Provider MAY require an Initial Access Token that is
provisioned out-of-band (in a manner that is out of scope for this
specification) to restrict registration requests to only authorized
Clients or developers."
  • Loading branch information
jogu authored and WilliamDenniss committed Sep 21, 2018
1 parent dd945e1 commit 0deb4e2
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 0 deletions.
33 changes: 33 additions & 0 deletions Source/OIDRegistrationRequest.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,16 @@ NS_ASSUME_NONNULL_BEGIN
*/
@property(nonatomic, readonly) OIDServiceConfiguration *configuration;

/*! @brief The initial access token to access the Client Registration Endpoint
(if required by the OpenID Provider).
@remarks OAuth 2.0 Access Token optionally issued by an Authorization Server granting
access to its Client Registration Endpoint. This token (if required) is
provisioned out of band.
@see Section 3 of OpenID Connect Dynamic Client Registration 1.0
https://openid.net/specs/openid-connect-registration-1_0.html#ClientRegistration
*/
@property(nonatomic, readonly) NSString *initialAccessToken;

/*! @brief The application type to register, will always be 'native'.
@remarks application_type
@see https://openid.net/specs/openid-connect-registration-1_0.html#ClientMetadata
Expand Down Expand Up @@ -79,6 +89,25 @@ NS_ASSUME_NONNULL_BEGIN
*/
- (instancetype)init NS_UNAVAILABLE;

/*! @brief Create a Client Registration Request to an OpenID Provider that supports open Dynamic
Registration.
@param configuration The service's configuration.
@param redirectURIs The redirect URIs to register for the client.
@param responseTypes The response types to register for the client.
@param grantTypes The grant types to register for the client.
@param subjectType The subject type to register for the client.
@param tokenEndpointAuthMethod The token endpoint authentication method to register for the
client.
@param additionalParameters The client's additional registration request parameters.
*/
- (instancetype)initWithConfiguration:(OIDServiceConfiguration *)configuration
redirectURIs:(NSArray<NSURL *> *)redirectURIs
responseTypes:(nullable NSArray<NSString *> *)responseTypes
grantTypes:(nullable NSArray<NSString *> *)grantTypes
subjectType:(nullable NSString *)subjectType
tokenEndpointAuthMethod:(nullable NSString *)tokenEndpointAuthMethod
additionalParameters:(nullable NSDictionary<NSString *, NSString *> *)additionalParameters;

/*! @brief Designated initializer.
@param configuration The service's configuration.
@param redirectURIs The redirect URIs to register for the client.
Expand All @@ -87,14 +116,18 @@ NS_ASSUME_NONNULL_BEGIN
@param subjectType The subject type to register for the client.
@param tokenEndpointAuthMethod The token endpoint authentication method to register for the
client.
@param initialAccessToken The initial access token to access the Client Registration Endpoint
(if required by the OpenID Provider).
@param additionalParameters The client's additional registration request parameters.
@see https://openid.net/specs/openid-connect-registration-1_0.html#ClientRegistration
*/
- (instancetype)initWithConfiguration:(OIDServiceConfiguration *)configuration
redirectURIs:(NSArray<NSURL *> *)redirectURIs
responseTypes:(nullable NSArray<NSString *> *)responseTypes
grantTypes:(nullable NSArray<NSString *> *)grantTypes
subjectType:(nullable NSString *)subjectType
tokenEndpointAuthMethod:(nullable NSString *)tokenEndpointAuthMethod
initialAccessToken:(nullable NSString *)initialAccessToken
additionalParameters:(nullable NSDictionary<NSString *, NSString *> *)additionalParameters
NS_DESIGNATED_INITIALIZER;

Expand Down
33 changes: 33 additions & 0 deletions Source/OIDRegistrationRequest.m
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@
*/
static NSString *const kConfigurationKey = @"configuration";

/*! @brief The key for the @c initialAccessToken property for @c NSSecureCoding
*/
static NSString *const kInitialAccessToken = @"initial_access_token";

/*! @brief Key used to encode the @c redirectURIs property for @c NSSecureCoding
*/
static NSString *const kRedirectURIsKey = @"redirect_uris";
Expand Down Expand Up @@ -69,9 +73,28 @@ - (instancetype)initWithConfiguration:(OIDServiceConfiguration *)configuration
subjectType:(nullable NSString *)subjectType
tokenEndpointAuthMethod:(nullable NSString *)tokenEndpointAuthenticationMethod
additionalParameters:(nullable NSDictionary<NSString *, NSString *> *)additionalParameters {
return [self initWithConfiguration:configuration
redirectURIs:redirectURIs
responseTypes:responseTypes
grantTypes:grantTypes
subjectType:subjectType
tokenEndpointAuthMethod:tokenEndpointAuthenticationMethod
initialAccessToken:nil
additionalParameters:additionalParameters];
}

- (instancetype)initWithConfiguration:(OIDServiceConfiguration *)configuration
redirectURIs:(NSArray<NSURL *> *)redirectURIs
responseTypes:(nullable NSArray<NSString *> *)responseTypes
grantTypes:(nullable NSArray<NSString *> *)grantTypes
subjectType:(nullable NSString *)subjectType
tokenEndpointAuthMethod:(nullable NSString *)tokenEndpointAuthenticationMethod
initialAccessToken:(nullable NSString *)initialAccessToken
additionalParameters:(nullable NSDictionary<NSString *, NSString *> *)additionalParameters {
self = [super init];
if (self) {
_configuration = [configuration copy];
_initialAccessToken = [initialAccessToken copy];
_redirectURIs = [redirectURIs copy];
_responseTypes = [responseTypes copy];
_grantTypes = [grantTypes copy];
Expand Down Expand Up @@ -105,6 +128,8 @@ - (instancetype)initWithCoder:(NSCoder *)aDecoder {
OIDServiceConfiguration *configuration =
[aDecoder decodeObjectOfClass:[OIDServiceConfiguration class]
forKey:kConfigurationKey];
NSString *initialAccessToken = [aDecoder decodeObjectOfClass:[NSString class]
forKey:kInitialAccessToken];
NSArray<NSURL *> *redirectURIs = [aDecoder decodeObjectOfClass:[NSArray<NSURL *> class]
forKey:kRedirectURIsKey];
NSArray<NSString *> *responseTypes = [aDecoder decodeObjectOfClass:[NSArray<NSString *> class]
Expand All @@ -127,12 +152,14 @@ - (instancetype)initWithCoder:(NSCoder *)aDecoder {
grantTypes:grantTypes
subjectType:subjectType
tokenEndpointAuthMethod:tokenEndpointAuthenticationMethod
initialAccessToken:initialAccessToken
additionalParameters:additionalParameters];
return self;
}

- (void)encodeWithCoder:(NSCoder *)aCoder {
[aCoder encodeObject:_configuration forKey:kConfigurationKey];
[aCoder encodeObject:_initialAccessToken forKey:kInitialAccessToken];
[aCoder encodeObject:_redirectURIs forKey:kRedirectURIsKey];
[aCoder encodeObject:_responseTypes forKey:kResponseTypesKey];
[aCoder encodeObject:_grantTypes forKey:kGrantTypesKey];
Expand All @@ -157,8 +184,10 @@ - (NSString *)description {

- (NSURLRequest *)URLRequest {
static NSString *const kHTTPPost = @"POST";
static NSString *const kBearer = @"Bearer";
static NSString *const kHTTPContentTypeHeaderKey = @"Content-Type";
static NSString *const kHTTPContentTypeHeaderValue = @"application/json";
static NSString *const kHTTPAuthorizationHeaderKey = @"Authorization";

NSData *postBody = [self JSONString];
if (!postBody) {
Expand All @@ -170,6 +199,10 @@ - (NSURLRequest *)URLRequest {
[[NSURLRequest requestWithURL:registrationRequestURL] mutableCopy];
URLRequest.HTTPMethod = kHTTPPost;
[URLRequest setValue:kHTTPContentTypeHeaderValue forHTTPHeaderField:kHTTPContentTypeHeaderKey];
if (_initialAccessToken) {
NSString *value = [NSString stringWithFormat:@"%@ %@", kBearer, _initialAccessToken];
[URLRequest setValue:value forHTTPHeaderField:kHTTPAuthorizationHeaderKey];
}
URLRequest.HTTPBody = postBody;
return URLRequest;
}
Expand Down
11 changes: 11 additions & 0 deletions UnitTests/OIDRegistrationRequestTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@
*/
static NSString *const kTestAdditionalParameterValue = @"1";

/*! @brief Test value for the @c initialAccessToken property.
*/
static NSString *const kInitialAccessTokenTestValue = @"test";

/*! @brief Test value for the @c redirectURL property.
*/
static NSString *kRedirectURLTestValue = @"https://client.example.com/redirect";
Expand Down Expand Up @@ -66,6 +70,7 @@ + (OIDRegistrationRequest *)testInstance {
grantTypes:@[ kGrantTypeTestValue ]
subjectType:kSubjectTypeTestValue
tokenEndpointAuthMethod:kTokenEndpointAuthMethodTestValue
initialAccessToken:kInitialAccessTokenTestValue
additionalParameters:additionalParameters];

return request;
Expand All @@ -84,6 +89,7 @@ - (void)testCopying {

XCTAssertNotNil(request.configuration);
XCTAssertEqualObjects(request.applicationType, OIDApplicationTypeNative);
XCTAssertEqualObjects(request.initialAccessToken, kInitialAccessTokenTestValue);
XCTAssertEqualObjects(request.redirectURIs, @[ [NSURL URLWithString:kRedirectURLTestValue] ]);
XCTAssertEqualObjects(request.responseTypes, @[ kResponseTypeTestValue ]);
XCTAssertEqualObjects(request.grantTypes, @[ kGrantTypeTestValue ]);
Expand All @@ -101,6 +107,7 @@ - (void)testCopying {
XCTAssertEqualObjects(requestCopy.configuration, request.configuration);

XCTAssertEqualObjects(requestCopy.applicationType, request.applicationType);
XCTAssertEqualObjects(requestCopy.initialAccessToken, kInitialAccessTokenTestValue);
XCTAssertEqualObjects(requestCopy.redirectURIs, request.redirectURIs);
XCTAssertEqualObjects(requestCopy.responseTypes, request.responseTypes);
XCTAssertEqualObjects(requestCopy.grantTypes, request.grantTypes);
Expand All @@ -120,6 +127,7 @@ - (void)testSecureCoding {

XCTAssertNotNil(request.configuration);
XCTAssertEqualObjects(request.applicationType, OIDApplicationTypeNative);
XCTAssertEqualObjects(request.initialAccessToken, kInitialAccessTokenTestValue);
XCTAssertEqualObjects(request.redirectURIs, @[ [NSURL URLWithString:kRedirectURLTestValue] ]);
XCTAssertEqualObjects(request.responseTypes, @[ kResponseTypeTestValue ]);
XCTAssertEqualObjects(request.grantTypes, @[ kGrantTypeTestValue ]);
Expand All @@ -139,6 +147,7 @@ - (void)testSecureCoding {
XCTAssertNotNil(requestCopy.configuration);

XCTAssertEqualObjects(requestCopy.applicationType, request.applicationType);
XCTAssertEqualObjects(requestCopy.initialAccessToken, kInitialAccessTokenTestValue);
XCTAssertEqualObjects(requestCopy.redirectURIs, request.redirectURIs);
XCTAssertEqualObjects(requestCopy.responseTypes, request.responseTypes);
XCTAssertEqualObjects(requestCopy.grantTypes, request.grantTypes);
Expand All @@ -162,6 +171,8 @@ - (void)testURLRequest {
XCTAssertEqualObjects(httpRequest.HTTPMethod, @"POST");
XCTAssertEqualObjects([httpRequest valueForHTTPHeaderField:@"Content-Type"],
@"application/json");
XCTAssertEqualObjects([httpRequest valueForHTTPHeaderField:@"Authorization"],
@"Bearer test");
XCTAssertEqualObjects(httpRequest.URL, request.configuration.registrationEndpoint);
XCTAssertEqualObjects(parsedJSON[OIDApplicationTypeParam], request.applicationType);
XCTAssertEqualObjects(parsedJSON[OIDRedirectURIsParam][0],
Expand Down

0 comments on commit 0deb4e2

Please sign in to comment.