-
Notifications
You must be signed in to change notification settings - Fork 66
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
added files from previous project, added podspec
- Loading branch information
Showing
7 changed files
with
294 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
// | ||
// Helpers.swift | ||
// Simplicity | ||
// | ||
// Created by Edward Jiang on 5/10/16. | ||
// Copyright © 2016 Stormpath. All rights reserved. | ||
// | ||
|
||
import Foundation | ||
|
||
class Helpers { | ||
static func registeredURLSchemes(matching closure: String -> Bool) -> [String] { | ||
guard let urlTypes = NSBundle.mainBundle().infoDictionary?["CFBundleURLTypes"] as? [[String: AnyObject]] else { | ||
return [String]() | ||
} | ||
|
||
// Convert the complex dictionary into an array of URL schemes | ||
let urlSchemes = urlTypes.flatMap({($0["CFBundleURLSchemes"] as? [String])?.first }) | ||
|
||
return urlSchemes.flatMap({closure($0) ? $0 : nil}) | ||
} | ||
|
||
static func queryString(parts: [String: String]) -> String? { | ||
return parts.map { $0 + "=" + $1 }.joinWithSeparator("&").stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet()) | ||
} | ||
} | ||
|
||
extension NSURL { | ||
/// Dictionary with key/value pairs from the URL fragment | ||
var fragmentDictionary: [String: String] { | ||
return dictionaryFromFormEncodedString(fragment) | ||
} | ||
|
||
/// Dictionary with key/value pairs from the URL query string | ||
var queryDictionary: [String: String] { | ||
return dictionaryFromFormEncodedString(query) | ||
} | ||
|
||
private func dictionaryFromFormEncodedString(input: String?) -> [String: String] { | ||
var result = [String: String]() | ||
|
||
guard let input = input else { | ||
return result | ||
} | ||
let inputPairs = input.componentsSeparatedByString("&") | ||
|
||
for pair in inputPairs { | ||
let split = pair.componentsSeparatedByString("=") | ||
if split.count == 2 { | ||
if let key = split[0].stringByRemovingPercentEncoding, value = split[1].stringByRemovingPercentEncoding { | ||
result[key] = value | ||
} | ||
} | ||
} | ||
return result | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
// | ||
// LoginProvider.swift | ||
// Simplicity | ||
// | ||
// Created by Edward Jiang on 5/10/16. | ||
// Copyright © 2016 Stormpath. All rights reserved. | ||
// | ||
|
||
import Foundation | ||
|
||
public protocol LoginProvider { | ||
var authorizationURL: NSURL { get } | ||
var urlScheme: String { get } | ||
|
||
func linkHandler(url: NSURL, callback: ExternalLoginCallback?) | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
// | ||
// Facebook.swift | ||
// Simplicity | ||
// | ||
// Created by Edward Jiang on 5/10/16. | ||
// Copyright © 2016 Stormpath. All rights reserved. | ||
// | ||
|
||
import Foundation | ||
|
||
public class FacebookLoginProvider: OAuth2LoginProvider { | ||
public var scopes = Set<String>() | ||
public var urlScheme: String | ||
|
||
public var state = arc4random_uniform(10000000) | ||
public var clientId: String | ||
public var grantType: OAuth2GrantType = .Custom | ||
|
||
|
||
public var authorizationURL: NSURL { | ||
// Auth_type is re-request since we need to ask for email scope again if | ||
// people decline the email permission. If it gets annoying because | ||
// people keep asking for more scopes, we can change this. | ||
|
||
let query = ["client_id": clientId, | ||
"redirect_uri": urlScheme + "://authorize", | ||
"response_type": "token", | ||
"scope": scopes.joinWithSeparator(" "), | ||
"auth_type": "rerequest", | ||
"state": String(state)] | ||
|
||
let queryString = Helpers.queryString(query)! | ||
|
||
return NSURL(string: "https://www.facebook.com/dialog/oauth?\(queryString)")! | ||
} | ||
|
||
public func linkHandler(url: NSURL, callback: ExternalLoginCallback?) { | ||
if(url.queryDictionary["error"] != nil) { | ||
// We are not even going to callback, because the user never started | ||
// the login process in the first place. Error is always because | ||
// people cancelled the FB login according to https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow | ||
return | ||
} | ||
|
||
// Get the access token, and check that the state is the same | ||
guard let accessToken = url.fragmentDictionary["access_token"] where url.fragmentDictionary["state"] == "\(state)" else { | ||
callback?(authToken: nil, error: nil) | ||
return | ||
} | ||
|
||
callback?(authToken: accessToken, error: nil) | ||
} | ||
|
||
public init?() { | ||
// Search for URL Scheme, error if not there | ||
|
||
guard let urlScheme = Helpers.registeredURLSchemes(matching: {$0.hasPrefix("fb")}).first, | ||
range = urlScheme.rangeOfString("\\d+", options: .RegularExpressionSearch) else { | ||
return nil | ||
} | ||
self.urlScheme = urlScheme | ||
self.clientId = urlScheme.substringWithRange(range) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
// | ||
// OAuth2LoginProvider.swift | ||
// Simplicity | ||
// | ||
// Created by Edward Jiang on 5/10/16. | ||
// Copyright © 2016 Stormpath. All rights reserved. | ||
// | ||
|
||
import Foundation | ||
|
||
public protocol OAuth2LoginProvider: LoginProvider { | ||
var clientId: String { get } | ||
var scopes: Set<String> { get set } | ||
var grantType: OAuth2GrantType { get } | ||
} | ||
|
||
public protocol OAuth2Scopes { | ||
var set: Set<String> { get set } | ||
var string: String { get } | ||
} | ||
|
||
public extension OAuth2Scopes { | ||
public var string: String { | ||
return set.joinWithSeparator(" ") | ||
} | ||
} | ||
|
||
public enum OAuth2GrantType { | ||
case AuthorizationCode, Implicit, Custom | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
// | ||
// Simplicity.swift | ||
// Simplicity | ||
// | ||
// Created by Edward Jiang on 5/10/16. | ||
// Copyright © 2016 Stormpath. All rights reserved. | ||
// | ||
|
||
import UIKit | ||
import SafariServices | ||
|
||
public typealias ExternalLoginCallback = (authToken: String?, error: NSError?) -> Void | ||
|
||
public class LoginManager: NSObject { | ||
static var currentLoginProvider: LoginProvider? | ||
static var callback: ExternalLoginCallback? | ||
static var safari: UIViewController? | ||
|
||
public static func login(loginProvider: LoginProvider, callback: ExternalLoginCallback? = nil) { | ||
self.currentLoginProvider = loginProvider | ||
self.callback = callback | ||
|
||
presentSafariView(loginProvider.authorizationURL) | ||
} | ||
|
||
/// Deep link handler (iOS9) | ||
public static func application(app: UIApplication, openURL url: NSURL, options: [String : AnyObject]) -> Bool { | ||
if url.scheme != currentLoginProvider?.urlScheme { | ||
return false | ||
} | ||
currentLoginProvider?.linkHandler(url, callback: callback) | ||
|
||
return true | ||
} | ||
|
||
/// Deep link handler (<iOS9) | ||
public static func application(application: UIApplication, openURL url: NSURL, sourceApplication: String?, annotation: AnyObject) -> Bool { | ||
return self.application(application, openURL: url, options: [String: AnyObject]()) | ||
} | ||
|
||
static func presentSafariView(url: NSURL) { | ||
if #available(iOS 9, *) { | ||
safari = SFSafariViewController(URL: url) | ||
UIApplication.sharedApplication().delegate?.window??.rootViewController?.presentViewController(safari!, animated: true, completion: nil) | ||
} else { | ||
UIApplication.sharedApplication().openURL(url) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
# | ||
# Be sure to run `pod lib lint Simplicity.podspec' to ensure this is a | ||
# valid spec before submitting. | ||
# | ||
# Any lines starting with a # are optional, but their use is encouraged | ||
# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html | ||
# | ||
|
||
Pod::Spec.new do |s| | ||
s.name = "Simplicity" | ||
s.version = "0.1.0" | ||
s.summary = "A framework for authenticating with external providers on iOS" | ||
|
||
# This description is used to generate tags and improve search results. | ||
# * Think: What does it do? Why did you write it? What is the focus? | ||
# * Try to keep it short, snappy and to the point. | ||
# * Write the description between the DESC delimiters below. | ||
# * Finally, don't worry about the indent, CocoaPods strips it! | ||
|
||
s.description = <<-DESC | ||
A framework for authenticating with external providers on iOS | ||
DESC | ||
|
||
s.homepage = "https://github.com/SimplicityMobile/Simplicity" | ||
# s.screenshots = "www.example.com/screenshots_1", "www.example.com/screenshots_2" | ||
s.license = 'Apache2' | ||
s.author = { "Edward Jiang" => "[email protected]" } | ||
s.source = { :git => "https://github.com/SimplicityMobile/Simplicity.git", :tag => s.version.to_s } | ||
# s.social_media_url = 'https://twitter.com/<TWITTER_USERNAME>' | ||
|
||
s.ios.deployment_target = '8.0' | ||
|
||
s.source_files = 'Simplicity/**/*.swift' | ||
|
||
# s.resource_bundles = { | ||
# 'Simplicity' => ['Simplicity/Assets/*.png'] | ||
# } | ||
|
||
s.public_header_files = 'Simplicity/**/*.h' | ||
# s.frameworks = 'UIKit', 'MapKit' | ||
# s.dependency 'AFNetworking', '~> 2.3' | ||
end |