Permalink
Browse files

Refactored OAuth support for merge into master. fixes #84, #211

Cleaned up @rodchile's excellent work integration OAuth 1.0 and 2.0 into RestKit. Changes
are as follows:

* Introduced new RKRequestAuthenticationType to replace the forceBasicAuthentication and other
    methods for influencing how authorization works.
* Moved TDOAuth code into Vendor/
* Renamed authorization code flow classes and delegate methods for clarity.
  • Loading branch information...
1 parent 144533c commit eb887e38c663c52603a78424e56fe30aae2fd912 @blakewatters blakewatters committed Sep 20, 2011
View
@@ -21,4 +21,5 @@ Docs/API
Examples/RKDiscussionBoardExample/discussion_board_backend/public/system/attachments/*
# UISpecRunner cached build path
-.uispec.app
+.uispec.app
+Specs/Runner/UISpec
@@ -26,3 +26,4 @@
#import "RKReachabilityObserver.h"
#import "RKRequestQueue.h"
#import "RKNotifications.h"
+#import "RKClientOAuth.h"
@@ -154,9 +154,15 @@ NSString* RKPathAppendQueryParams(NSString* resourcePath, NSDictionary* queryPar
*/
@interface RKClient : NSObject {
NSString *_baseURL;
+ RKRequestAuthenticationType _authenticationType;
NSString *_username;
NSString *_password;
- BOOL _forceBasicAuthentication;
+ NSString *_OAuth1ConsumerKey;
+ NSString *_OAuth1ConsumerSecret;
+ NSString *_OAuth1AccessToken;
+ NSString *_OAuth1AccessTokenSecret;
+ NSString *_OAuth2AccessToken;
+ NSString *_OAuth2RefreshToken;
NSMutableDictionary *_HTTPHeaders;
RKReachabilityObserver *_baseURLReachabilityObserver;
NSString *_serviceUnavailableAlertTitle;
@@ -249,10 +255,23 @@ NSString* RKPathAppendQueryParams(NSString* resourcePath, NSDictionary* queryPar
#endif
/////////////////////////////////////////////////////////////////////////
-/// @name HTTP Authentication
+/// @name Authentication
/////////////////////////////////////////////////////////////////////////
/**
+ The type of authentication to use for this request.
+
+ When configured to RKRequestAuthenticationTypeHTTPBasic, RestKit will add
+ an Authorization header establishing login via HTTP Basic. This is an optimization
+ that skips the challenge portion of the request.
+
+ **Default**: RKRequestAuthenticationTypeNone
+
+ @see RKRequestAuthenticationType
+ */
+@property (nonatomic, assign) RKRequestAuthenticationType authenticationType;
+
+/**
* The username to use for authentication via HTTP AUTH
*/
@property(nonatomic, retain) NSString *username;
@@ -262,14 +281,43 @@ NSString* RKPathAppendQueryParams(NSString* resourcePath, NSDictionary* queryPar
*/
@property(nonatomic, retain) NSString *password;
+/*** @name OAuth Secrets */
+
/**
- When YES, RKRequest objects dispatched through the client will have an HTTP Basic
- Authorization header added before being sent.
-
- This avoids an HTTP AUTH challenge before authentication and can be used to force
- authentication is situations where an AUTH challenge is not issued
+ The OAuth 1.0 consumer key
+ */
+@property(nonatomic,retain) NSString *OAuth1ConsumerKey;
+
+/**
+ The OAuth 1.0 consumer secret
+ */
+@property(nonatomic,retain) NSString *OAuth1ConsumerSecret;
+
+/**
+ The OAuth 1.0 access token
+ */
+@property(nonatomic,retain) NSString *OAuth1AccessToken;
+
+/**
+ The OAuth 1.0 access token secret
+ */
+@property(nonatomic,retain) NSString *OAuth1AccessTokenSecret;
+
+/*** @name OAuth2 Secrets */
+
+/**
+ The OAuth 2.0 access token
*/
-@property(nonatomic, assign) BOOL forceBasicAuthentication;
+@property(nonatomic,retain) NSString *OAuth2AccessToken;
+
+/**
+ The OAuth 2.0 refresh token. Used to retrieve a new access token before expiration
+ */
+@property(nonatomic,retain) NSString *OAuth2RefreshToken;
+
+/////////////////////////////////////////////////////////////////////////
+/// @name Reachability & Service Availability Alerting
+/////////////////////////////////////////////////////////////////////////
/**
* The RKReachabilityObserver used to monitor whether or not the client has a connection
@@ -283,10 +331,6 @@ NSString* RKPathAppendQueryParams(NSString* resourcePath, NSDictionary* queryPar
*/
@property(nonatomic, readonly) RKReachabilityObserver *baseURLReachabilityObserver;
-/////////////////////////////////////////////////////////////////////////
-/// @name Service Availability Alerting
-/////////////////////////////////////////////////////////////////////////
-
/**
* The title to use in the alert shown when a request encounters a
* ServiceUnavailable (503) response.
@@ -68,9 +68,15 @@
@implementation RKClient
@synthesize baseURL = _baseURL;
+@synthesize authenticationType = _authenticationType;
@synthesize username = _username;
@synthesize password = _password;
-@synthesize forceBasicAuthentication = _forceBasicAuthentication;
+@synthesize OAuth1ConsumerKey = _OAuth1ConsumerKey;
+@synthesize OAuth1ConsumerSecret = _OAuth1ConsumerSecret;
+@synthesize OAuth1AccessToken = _OAuth1AccessToken;
+@synthesize OAuth1AccessTokenSecret = _OAuth1AccessTokenSecret;
+@synthesize OAuth2AccessToken = _OAuth2AccessToken;
+@synthesize OAuth2RefreshToken = _OAuth2RefreshToken;
@synthesize HTTPHeaders = _HTTPHeaders;
#ifdef RESTKIT_SSL_VALIDATION
@synthesize additionalRootCertificates = _additionalRootCertificates;
@@ -102,7 +108,6 @@ + (RKClient *)clientWithBaseURL:(NSString *)baseURL username:(NSString *)usernam
RKClient *client = [RKClient clientWithBaseURL:baseURL];
client.username = username;
client.password = password;
-
return client;
}
@@ -201,16 +206,22 @@ - (NSURL *)URLForResourcePath:(NSString *)resourcePath queryParams:(NSDictionary
- (void)setupRequest:(RKRequest *)request {
request.additionalHTTPHeaders = _HTTPHeaders;
+ request.authenticationType = self.authenticationType;
request.username = self.username;
request.password = self.password;
- request.forceBasicAuthentication = self.forceBasicAuthentication;
request.cachePolicy = self.cachePolicy;
request.cache = self.requestCache;
- request.queue = self.requestQueue;
+ request.queue = self.requestQueue;
- if (! [self.requestQueue isKindOfClass:[RKRequestQueue class]]) {
- NSLog(@"BREAK)@($&@()$");
- }
+ // OAuth 1 Parameters
+ request.OAuth1AccessToken = self.OAuth1AccessToken;
+ request.OAuth1AccessTokenSecret = self.OAuth1AccessTokenSecret;
+ request.OAuth1ConsumerKey = self.OAuth1ConsumerKey;
+ request.OAuth1ConsumerSecret = self.OAuth1ConsumerSecret;
+
+ // OAuth2 Parameters
+ request.OAuth2AccessToken = self.OAuth2AccessToken;
+ request.OAuth2RefreshToken = self.OAuth2RefreshToken;
}
- (void)setValue:(NSString *)value forHTTPHeaderField:(NSString *)header {
@@ -0,0 +1,127 @@
+//
+// RKOAuthClient.h
+// RestKit
+//
+// Created by Rodrigo Garcia on 7/20/11.
+// Copyright 2011 RestKit. All rights reserved.
+//
+// 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 <UIKit/UIKit.h>
+#import <Foundation/Foundation.h>
+#import "RKClient.h"
+#import "RKRequest.h"
+
+/**
+ Defines error codes for OAuth client errors
+ */
+typedef enum RKOAuthClientErrors {
+ RKOAuthClientErrorInvalidGrant = 3001, // An invalid authorization code was encountered
+ RKOAuthClientErrorUnauthorizedClient = 3002, // The client is not authorized to perform the action
+ RKOAuthClientErrorInvalidClient = 3003, //
+ RKOAuthClientErrorInvalidRequest = 3004, //
+ RKOAuthClientErrorUnsupportedGrantType = 3005, //
+ RKOAuthClientErrorInvalidScope = 3006, //
+ RKOAuthClientErrorRequestError = 3007 //
+} RKOAuthClientErrorCode;
+
+@protocol RKOAuthClientDelegate;
+
+/**
+ An OAuth client implementation used for OAuth 2 authorization code flow.
+ */
+@interface RKOAuthClient : NSObject <RKRequestDelegate> {
+ NSString *_clientID;
+ NSString *_clientSecret;
+ NSString *_authorizationCode;
+ NSString *_authorizationURL;
+ NSString *_callbackURL;
+ NSString *_accessToken;
+ id<RKOAuthClientDelegate> _delegate;
+}
+
+// General properties of the client
+@property(nonatomic,retain) NSString *authorizationCode;
+
+// OAuth Client ID and Secret
+@property(nonatomic,retain) NSString *clientID;
+@property(nonatomic,retain) NSString *clientSecret;
+
+// OAuth EndPoints
+@property(nonatomic,retain) NSString *authorizationURL;
+@property(nonatomic,retain) NSString *callbackURL;
+
+/**
+ Returns the access token retrieved
+ */
+@property (nonatomic, readonly) NSString *accessToken;
+
+// Client Delegate
+@property (nonatomic,assign) id<RKOAuthClientDelegate> delegate;
+
+- (id)initWithClientID:(NSString *)clientId
+ secret:(NSString *)secret
+ delegate:(id<RKOAuthClientDelegate>)delegate;
+
+- (void)validateAuthorizationCode;
+
++ (RKOAuthClient *)clientWithClientID:(NSString *)clientId
+ secret:(NSString *)secret
+ delegate:(id<RKOAuthClientDelegate>)delegate;
+
+@end
+
+/**
+ * Lifecycle events for RKClientOAuth
+ */
+@protocol RKOAuthClientDelegate <NSObject>
+@required
+
+/**
+ * Sent when a new access token has being acquired
+ */
+- (void)OAuthClient:(RKOAuthClient *)client didAcquireAccessToken:(NSString *)token;
+
+/**
+ * Sent when an access token request has failed due an invalid authorization code
+ */
+- (void)OAuthClient:(RKOAuthClient *)client didFailWithInvalidGrantError:(NSError *)error;
+
+@optional
+
+/**
+ * Other OAuth2 protocol exceptions for the authorization code flow
+ */
+
+/**
+ Sent to the delegate when the OAuth client encounters any error
+ */
+- (void)OAuthClient:(RKOAuthClient *)client didFailWithError:(NSError *)error;
+
+- (void)OAuthClient:(RKOAuthClient *)client didFailWithUnauthorizedClientError:(NSError *)error;
+
+- (void)OAuthClient:(RKOAuthClient *)client didFailWithInvalidClientError:(NSError *)error;
+
+- (void)OAuthClient:(RKOAuthClient *)client didFailWithInvalidRequestError:(NSError *)error;
+
+- (void)OAuthClient:(RKOAuthClient *)client didFailWithUnsupportedGrantTypeError:(NSError *)error;
+
+- (void)OAuthClient:(RKOAuthClient *)client didFailWithInvalidScopeError:(NSError *)error;
+
+/**
+ Sent to the delegate when an authorization code flow request failed loading due to an error
+ */
+- (void)OAuthClient:(RKOAuthClient *)client didFailLoadingRequest:(RKRequest *)request withError:(NSError *)error;
+
+@end
Oops, something went wrong.

0 comments on commit eb887e3

Please sign in to comment.