Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

[oauth] Add Github OAuth 2.0 support.

  • Loading branch information...
commit e58cb07c65ed4a74ae1b3d860c35d22168cd28ba 1 parent ad0e71b
@jverkoey authored
View
12 examples/oauth/OAuthCatalog/OAuthCatalog.xcodeproj/project.pbxproj
@@ -7,6 +7,8 @@
objects = {
/* Begin PBXBuildFile section */
+ 66A69748151A566E0076FC25 /* NIGithubOpenAuthenticator.m in Sources */ = {isa = PBXBuildFile; fileRef = 66A69747151A566E0076FC25 /* NIGithubOpenAuthenticator.m */; };
+ 66A69750151A5E150076FC25 /* GithubController.m in Sources */ = {isa = PBXBuildFile; fileRef = 66A6974F151A5E150076FC25 /* GithubController.m */; };
66DC73E714F499FD0077DAB0 /* NIWebController.m in Sources */ = {isa = PBXBuildFile; fileRef = 66DC73E614F499FD0077DAB0 /* NIWebController.m */; };
66EDE08E14F1A1A10002B92B /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 66EDE08D14F1A1A10002B92B /* UIKit.framework */; };
66EDE09014F1A1A10002B92B /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 66EDE08F14F1A1A10002B92B /* Foundation.framework */; };
@@ -50,6 +52,10 @@
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
+ 66A69746151A566E0076FC25 /* NIGithubOpenAuthenticator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NIGithubOpenAuthenticator.h; path = ../../../src/oauth/src/NIGithubOpenAuthenticator.h; sourceTree = "<group>"; };
+ 66A69747151A566E0076FC25 /* NIGithubOpenAuthenticator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = NIGithubOpenAuthenticator.m; path = ../../../src/oauth/src/NIGithubOpenAuthenticator.m; sourceTree = "<group>"; };
+ 66A6974E151A5E150076FC25 /* GithubController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GithubController.h; sourceTree = "<group>"; };
+ 66A6974F151A5E150076FC25 /* GithubController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GithubController.m; sourceTree = "<group>"; };
66DC73E314F499FD0077DAB0 /* NimbusWebController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NimbusWebController.h; path = ../../../src/webcontroller/src/NimbusWebController.h; sourceTree = "<group>"; };
66DC73E414F499FD0077DAB0 /* NimbusWebController+Namespace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NimbusWebController+Namespace.h"; path = "../../../src/webcontroller/src/NimbusWebController+Namespace.h"; sourceTree = "<group>"; };
66DC73E514F499FD0077DAB0 /* NIWebController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NIWebController.h; path = ../../../src/webcontroller/src/NIWebController.h; sourceTree = "<group>"; };
@@ -299,6 +305,8 @@
66EDE0ED14F1A1E10002B92B /* NIOpenAuthenticator+Subclassing.h */,
66EDE10F14F1CEA60002B92B /* NISoundCloudOpenAuthenticator.h */,
66EDE11014F1CEA60002B92B /* NISoundCloudOpenAuthenticator.m */,
+ 66A69746151A566E0076FC25 /* NIGithubOpenAuthenticator.h */,
+ 66A69747151A566E0076FC25 /* NIGithubOpenAuthenticator.m */,
66EDE11F14F1DABC0002B92B /* NIKeychainPassword.h */,
66EDE12014F1DABD0002B92B /* NIKeychainPassword.m */,
);
@@ -310,6 +318,8 @@
children = (
66EDE0F014F1A2620002B92B /* CatalogTableViewController.h */,
66EDE0F114F1A2620002B92B /* CatalogTableViewController.m */,
+ 66A6974E151A5E150076FC25 /* GithubController.h */,
+ 66A6974F151A5E150076FC25 /* GithubController.m */,
66EDE10414F1A68D0002B92B /* SoundCloudController.h */,
66EDE10514F1A68D0002B92B /* SoundCloudController.m */,
);
@@ -460,6 +470,8 @@
66EDE11A14F1D51D0002B92B /* TableViewKeyValue.m in Sources */,
66EDE12114F1DABD0002B92B /* NIKeychainPassword.m in Sources */,
66DC73E714F499FD0077DAB0 /* NIWebController.m in Sources */,
+ 66A69748151A566E0076FC25 /* NIGithubOpenAuthenticator.m in Sources */,
+ 66A69750151A5E150076FC25 /* GithubController.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
View
3  examples/oauth/OAuthCatalog/OAuthCatalog/CatalogTableViewController.m
@@ -16,6 +16,7 @@
#import "CatalogTableViewController.h"
+#import "GithubController.h"
#import "SoundCloudController.h"
#import "TableViewText.h"
@@ -39,6 +40,8 @@ - (id)initWithStyle:(UITableViewStyle)style {
NSArray* objects = [NSArray arrayWithObjects:
@"Services",
+ [TableViewText objectWithText:@"Github"
+ object:[GithubController class]],
[TableViewText objectWithText:@"SoundCloud"
object:[SoundCloudController class]],
nil];
View
20 examples/oauth/OAuthCatalog/OAuthCatalog/GithubController.h
@@ -0,0 +1,20 @@
+//
+// Copyright 2012 Jeff Verkoeyen
+//
+// 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>
+
+@interface GithubController : UITableViewController
+@end
View
111 examples/oauth/OAuthCatalog/OAuthCatalog/GithubController.m
@@ -0,0 +1,111 @@
+//
+// Copyright 2012 Jeff Verkoeyen
+//
+// 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 "GithubController.h"
+
+#import "TableViewText.h"
+#import "TableViewKeyValue.h"
+#import "NIGithubOpenAuthenticator.h"
+
+static NSString* const kClientIdentifier = @"5ba59bf2ac97dfbdc280";
+static NSString* const kClientSecret = @"bac6e9a230ae40f6430ab18eb351b89c57cbf66b";
+
+typedef enum {
+ AuthenticateAction = 1,
+ DeauthenticateAction,
+} Actions;
+
+@interface GithubController()
+@property (nonatomic, readwrite, retain) NIGithubOpenAuthenticator* auth;
+@property (nonatomic, readwrite, retain) NITableViewModel* model;
+@end
+
+@implementation GithubController
+
+@synthesize auth = _auth;
+@synthesize model = _model;
+
+- (void)dealloc {
+ [_auth release];
+ [_model release];
+
+ [super dealloc];
+}
+
+- (id)initWithStyle:(UITableViewStyle)style {
+ if ((self = [super initWithStyle:style])) {
+ self.auth = [[[NIGithubOpenAuthenticator alloc] initWithClientIdentifier:kClientIdentifier
+ clientSecret:kClientSecret] autorelease];
+ self.title = @"Github";
+ }
+ return self;
+}
+
+- (void)refreshModel {
+ NSMutableArray* objects = [NSMutableArray array];
+ if (NIOpenAuthenticationStateAuthorized == self.auth.state) {
+ [objects addObject:[TableViewText objectWithText:@"Authenticated!"
+ object:nil]];
+
+ [objects addObject:[TableViewText objectWithText:@"De-authenticate"
+ object:[NSNumber numberWithInt:DeauthenticateAction]]];
+
+ [objects addObject:[NITableViewModelFooter footerWithTitle:self.auth.oauthToken]];
+
+ } else if (NIOpenAuthenticationStateFetchingToken == self.auth.state) {
+ [objects addObject:[TableViewText objectWithText:@"Authenticating..."
+ object:nil]];
+
+ } else {
+ [objects addObject:[TableViewText objectWithText:@"Authenticate"
+ object:[NSNumber numberWithInt:AuthenticateAction]]];
+ }
+ self.model = [[[NITableViewModel alloc] initWithSectionedArray:objects
+ delegate:(id)[NICellFactory class]]autorelease];
+ self.tableView.dataSource = self.model;
+}
+
+- (void)viewDidLoad {
+ [super viewDidLoad];
+
+ [self refreshModel];
+}
+
+- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
+ TableViewText* textObject = [self.model objectAtIndexPath:indexPath];
+ if (nil == textObject.object) {
+ return;
+ }
+
+ switch ([textObject.object intValue]) {
+ case AuthenticateAction: {
+ [self.auth authenticateWithStateHandler:
+ ^(NIOpenAuthenticator* auth, NIOpenAuthenticationState state, NSError* error) {
+ [self refreshModel];
+ [self.tableView reloadData];
+ }];
+ break;
+ }
+ case DeauthenticateAction: {
+ [self.auth clearAuthentication];
+ [self refreshModel];
+ [self.tableView reloadData];
+ break;
+ }
+ }
+}
+
+@end
View
3  examples/oauth/OAuthCatalog/OAuthCatalog/SoundCloudController.m
@@ -18,6 +18,7 @@
#import "TableViewText.h"
#import "TableViewKeyValue.h"
+#import "NISoundCloudOpenAuthenticator.h"
static NSString* const kClientIdentifier = @"41381b580d073d076059a96d17da2e2e";
static NSString* const kClientSecret = @"c35bb8d143e13255c2addca65e59a34d";
@@ -62,6 +63,8 @@ - (void)refreshModel {
[objects addObject:[TableViewText objectWithText:@"De-authenticate"
object:[NSNumber numberWithInt:DeauthenticateAction]]];
+ [objects addObject:[NITableViewModelFooter footerWithTitle:self.auth.oauthToken]];
+
} else if (NIOpenAuthenticationStateFetchingToken == self.auth.state) {
[objects addObject:[TableViewText objectWithText:@"Authenticating..."
object:nil]];
View
8 src/Nimbus.xcodeproj/project.pbxproj
@@ -280,6 +280,8 @@
66A0B0CC14BD15CA003FA413 /* UIView+NimbusCore.h in Headers */ = {isa = PBXBuildFile; fileRef = 66A0B0CA14BD15CA003FA413 /* UIView+NimbusCore.h */; };
66A0B0CD14BD15CA003FA413 /* UIView+NimbusCore.m in Sources */ = {isa = PBXBuildFile; fileRef = 66A0B0CB14BD15CA003FA413 /* UIView+NimbusCore.m */; };
66A0B0D014BD1635003FA413 /* NimbusNetworkControllers+Namespace.h in Headers */ = {isa = PBXBuildFile; fileRef = 66A0B0CF14BD1635003FA413 /* NimbusNetworkControllers+Namespace.h */; };
+ 66A6974B151A56780076FC25 /* NITwitterOpenAuthenticator.h in Headers */ = {isa = PBXBuildFile; fileRef = 66A69749151A56780076FC25 /* NITwitterOpenAuthenticator.h */; };
+ 66A6974C151A56780076FC25 /* NITwitterOpenAuthenticator.m in Sources */ = {isa = PBXBuildFile; fileRef = 66A6974A151A56780076FC25 /* NITwitterOpenAuthenticator.m */; };
66B10900144C931F004576D1 /* UIButton+NIStyleable.h in Headers */ = {isa = PBXBuildFile; fileRef = 66B108FE144C931F004576D1 /* UIButton+NIStyleable.h */; };
66B10901144C931F004576D1 /* UIButton+NIStyleable.m in Sources */ = {isa = PBXBuildFile; fileRef = 66B108FF144C931F004576D1 /* UIButton+NIStyleable.m */; };
66C113E5147DD0F1003C9AC6 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 66832D00143E38E6003E413C /* UIKit.framework */; };
@@ -873,6 +875,8 @@
66A0B0CA14BD15CA003FA413 /* UIView+NimbusCore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIView+NimbusCore.h"; sourceTree = "<group>"; };
66A0B0CB14BD15CA003FA413 /* UIView+NimbusCore.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIView+NimbusCore.m"; sourceTree = "<group>"; };
66A0B0CF14BD1635003FA413 /* NimbusNetworkControllers+Namespace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NimbusNetworkControllers+Namespace.h"; path = "networkcontrollers/src/NimbusNetworkControllers+Namespace.h"; sourceTree = SOURCE_ROOT; };
+ 66A69749151A56780076FC25 /* NITwitterOpenAuthenticator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NITwitterOpenAuthenticator.h; path = oauth/src/NITwitterOpenAuthenticator.h; sourceTree = SOURCE_ROOT; };
+ 66A6974A151A56780076FC25 /* NITwitterOpenAuthenticator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = NITwitterOpenAuthenticator.m; path = oauth/src/NITwitterOpenAuthenticator.m; sourceTree = SOURCE_ROOT; };
66B108FE144C931F004576D1 /* UIButton+NIStyleable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "UIButton+NIStyleable.h"; path = "css/src/UIButton+NIStyleable.h"; sourceTree = SOURCE_ROOT; };
66B108FF144C931F004576D1 /* UIButton+NIStyleable.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "UIButton+NIStyleable.m"; path = "css/src/UIButton+NIStyleable.m"; sourceTree = SOURCE_ROOT; };
66B10906144D4C15004576D1 /* deps */ = {isa = PBXFileReference; lastKnownFileType = text; name = deps; path = css/deps; sourceTree = SOURCE_ROOT; };
@@ -1468,6 +1472,8 @@
66EDE07A14F1A01F0002B92B /* NIOpenAuthenticator+Subclassing.h */,
66EDE10B14F1CCEC0002B92B /* NISoundCloudOpenAuthenticator.h */,
66EDE10C14F1CCEC0002B92B /* NISoundCloudOpenAuthenticator.m */,
+ 66A69749151A56780076FC25 /* NITwitterOpenAuthenticator.h */,
+ 66A6974A151A56780076FC25 /* NITwitterOpenAuthenticator.m */,
66DC73D414F4237A0077DAB0 /* NIKeychainPassword.h */,
66DC73D514F4237A0077DAB0 /* NIKeychainPassword.m */,
);
@@ -2105,6 +2111,7 @@
66EDE07C14F1A01F0002B92B /* NIOpenAuthenticator+Subclassing.h in Headers */,
66EDE10D14F1CCEC0002B92B /* NISoundCloudOpenAuthenticator.h in Headers */,
66DC73D614F4237A0077DAB0 /* NIKeychainPassword.h in Headers */,
+ 66A6974B151A56780076FC25 /* NITwitterOpenAuthenticator.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -3418,6 +3425,7 @@
66759B5714DCC04C0094C24B /* NIOpenAuthenticator.m in Sources */,
66EDE10E14F1CCEC0002B92B /* NISoundCloudOpenAuthenticator.m in Sources */,
66DC73D714F4237A0077DAB0 /* NIKeychainPassword.m in Sources */,
+ 66A6974C151A56780076FC25 /* NITwitterOpenAuthenticator.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
View
43 src/oauth/src/NIGithubOpenAuthenticator.h
@@ -0,0 +1,43 @@
+//
+// Copyright 2012 Jeff Verkoeyen
+//
+// 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 "NIOpenAuthenticator.h"
+
+/**
+ * An Rdio OAuth 2.0 implementation.
+ *
+ * This provides support for authenticating against the Github API outlined here:
+ * http://developer.github.com/v3/
+ *
+ * <h1>Registering a Github Application</h1>
+ *
+ * To register a Github application for use with the Nimbus OAuth API, please follow the
+ * following steps.
+ *
+ * 1) Create a Github account at http://github.com/
+ * 2) Create a new application at https://github.com/settings/applications/new
+ * 4) Provide a name for your application and url for your application's website.
+ * 5) Enter the following value in the Redirect URI input:
+ * <your application URL prefix>://oauth/github
+ * 6) Click "Register application".
+ * 7) Follow the generic directions for using the Nimbus OAuth API in your application. You will
+ * find your Client ID and Client Secret on your application's information page.
+ *
+ * @ingroup NimbusOAuth
+ * @class NIGithubOpenAuthenticator
+ */
+@interface NIGithubOpenAuthenticator : NIOpenAuthenticator
+@end
View
50 src/oauth/src/NIGithubOpenAuthenticator.m
@@ -0,0 +1,50 @@
+//
+// Copyright 2012 Jeff Verkoeyen
+//
+// 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 "NIGithubOpenAuthenticator.h"
+
+#import "NIOpenAuthenticator+Subclassing.h"
+#import "NimbusCore.h"
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////////
+@implementation NIGithubOpenAuthenticator
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+- (NSString *)applicationRedirectPath {
+ return [[super applicationRedirectPath] stringByAppendingString:@"/github"];
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+- (NSURL *)authenticationUrl {
+ return [NSURL URLWithString:
+ [NSString stringWithFormat:
+ @"https://github.com/login/oauth/authorize?client_id=%@&redirect_uri=%@",
+ self.clientIdentifier,
+ self.applicationRedirectPath]];
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+- (NSURL *)tokenUrl {
+ return [NSURL URLWithString:@"https://github.com/login/oauth/access_token"];
+}
+
+@end
View
47 src/oauth/src/NIOpenAuthenticator.m
@@ -221,28 +221,47 @@ - (void)fetchToken {
NINetworkActivityTaskDidFinish();
NSString* result = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease];
- BOOL didFindToken = NO;
+ NSString* accessToken = nil;
+
+ // JSON return type.
id object = [result objectFromJSONString];
if ([object isKindOfClass:[NSDictionary class]]) {
NSDictionary* results = object;
if ([results objectForKey:@"access_token"]) {
- self.oauthToken = [results objectForKey:@"access_token"];
- self.keychain.password = self.oauthToken;
-
- didFindToken = YES;
- self.state = NIOpenAuthenticationStateAuthorized;
- if (nil != self.stateHandler) {
- // The state handler may interact with UI so we must ensure that the
- // block is executed on the main thread.
- dispatch_async(dispatch_get_main_queue(), ^{
- self.stateHandler(self, NIOpenAuthenticationStateAuthorized, nil);
- self.stateHandler = nil;
- });
+ accessToken = [results objectForKey:@"access_token"];
+ }
+
+ } else if (nil == object) {
+ // URL parameters return type.
+ NSArray* components = [result componentsSeparatedByString:@"&"];
+ for (NSString *component in components) {
+ NSArray* parts = [component componentsSeparatedByString:@"="];
+ if (parts.count == 2) {
+ NSString* key = [parts objectAtIndex:0];
+ NSString* value = [parts objectAtIndex:1];
+ if ([key isEqualToString:@"access_token"]) {
+ accessToken = value;
+ break;
+ }
}
}
}
- if (!didFindToken) {
+ if (NIIsStringWithAnyText(accessToken)) {
+ self.oauthToken = accessToken;
+ self.keychain.password = self.oauthToken;
+
+ self.state = NIOpenAuthenticationStateAuthorized;
+ if (nil != self.stateHandler) {
+ // The state handler may interact with UI so we must ensure that the
+ // block is executed on the main thread.
+ dispatch_async(dispatch_get_main_queue(), ^{
+ self.stateHandler(self, NIOpenAuthenticationStateAuthorized, nil);
+ self.stateHandler = nil;
+ });
+ }
+
+ } else {
self.state = NIOpenAuthenticationStateInactive;
if (nil != self.stateHandler) {
// The state handler may interact with UI so we must ensure that the
View
1  src/oauth/src/NimbusOAuth.h
@@ -24,4 +24,3 @@
*/
#import "NIOpenAuthenticator.h"
-#import "NISoundCloudOpenAuthenticator.h"
Please sign in to comment.
Something went wrong with that request. Please try again.