This repository was archived by the owner on Sep 16, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 52
/
Copy pathOAuth2AppOnlyToken.swift
120 lines (110 loc) · 4.84 KB
/
OAuth2AppOnlyToken.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
//
// OAuth2AppOnlyToken.swift
// reddift
//
// Created by sonson on 2015/05/05.
// Copyright (c) 2015年 sonson. All rights reserved.
//
import Foundation
/**
OAuth2Token extension to authorize without a user context.
This class is private and for only unit testing because "Installed app" is prohibited from using "Application Only OAuth" scheme, that is without user context.
*/
public struct OAuth2AppOnlyToken: Token {
public static let baseURL = "https://www.reddit.com/api/v1"
public let accessToken: String
public let tokenType: String
public let expiresIn: Int
public let scope: String
public let refreshToken: String
public let name: String
public let expiresDate: TimeInterval
/**
Time inteval the access token expires from being authorized.
*/
// public var expiresIn:Int {
// set (newValue) { _expiresIn = newValue; expiresDate = NSDate.timeIntervalSinceReferenceDate() + Double(_expiresIn) }
// get { return _expiresIn }
// }
/**
Initialize vacant OAuth2AppOnlyToken with JSON.
*/
public init() {
self.name = ""
self.accessToken = ""
self.tokenType = ""
self.expiresIn = 0
self.scope = ""
self.refreshToken = ""
self.expiresDate = Date.timeIntervalSinceReferenceDate + 0
}
/**
Initialize OAuth2AppOnlyToken with JSON.
- parameter json: JSON as JSONDictionary should include "name", "access_token", "token_type", "expires_in", "scope" and "refresh_token".
*/
public init(_ json: JSONDictionary) {
self.name = json["name"] as? String ?? ""
self.accessToken = json["access_token"] as? String ?? ""
self.tokenType = json["token_type"] as? String ?? ""
let expiresIn = json["expires_in"] as? Int ?? 0
self.expiresIn = expiresIn
self.expiresDate = json["expires_date"] as? TimeInterval ?? Date.timeIntervalSinceReferenceDate + Double(expiresIn)
self.scope = json["scope"] as? String ?? ""
self.refreshToken = json["refresh_token"] as? String ?? ""
}
/**
Create URLRequest object to request getting an access token.
- parameter code: The code which is obtained from OAuth2 redict URL at reddit.com.
- returns: URLRequest object to request your access token.
*/
public static func requestForOAuth2AppOnly(username: String, password: String, clientID: String, secret: String) -> URLRequest? {
guard let URL = URL(string: "https://ssl.reddit.com/api/v1/access_token") else { return nil }
var request = URLRequest(url: URL)
do {
try request.setRedditBasicAuthentication(username: clientID, password: secret)
let param = "grant_type=password&username=" + username + "&password=" + password
let data = param.data(using: .utf8)
request.httpBody = data
request.httpMethod = "POST"
return request
} catch {
print(error)
return nil
}
}
/**
Request to get a new access token.
- parameter code: Code to be confirmed your identity by reddit.
- parameter completion: The completion handler to call when the load request is complete.
- returns: Data task which requests search to reddit.com.
*/
@discardableResult
public static func getOAuth2AppOnlyToken(username: String, password: String, clientID: String, secret: String, completion: @escaping (Result<Token>) -> Void) throws -> URLSessionDataTask {
let session = URLSession(configuration: URLSessionConfiguration.default)
guard let request = requestForOAuth2AppOnly(username: username, password: password, clientID: clientID, secret: secret)
else { throw ReddiftError.canNotCreateURLRequest as NSError }
let task = session.dataTask(with: request, completionHandler: { (data: Data?, response: URLResponse?, error: Error?) -> Void in
let result = Result(from: Response(data: data, urlResponse: response), optional: error as NSError?)
.flatMap(response2Data)
.flatMap(data2Json)
.flatMap({(json: JSONAny) -> Result<JSONDictionary> in
if let json = json as? JSONDictionary {
return Result(value: json)
}
return Result(error: ReddiftError.tokenJsonObjectIsNotDictionary as NSError)
})
var token: OAuth2AppOnlyToken? = nil
switch result {
case .success(let json):
var newJSON = json
newJSON["name"] = username as AnyObject
token = OAuth2AppOnlyToken(newJSON)
default:
break
}
completion(Result(fromOptional: token, error: ReddiftError.unknown as NSError))
})
task.resume()
return task
}
}