11
11
12
12
abstract class OAuth2_Provider {
13
13
14
+ /**
15
+ * Create a new provider.
16
+ *
17
+ * // Load the Twitter provider
18
+ * $provider = OAuth2_Provider::forge('twitter');
19
+ *
20
+ * @param string provider name
21
+ * @param array provider options
22
+ * @return OAuth_Provider
23
+ */
24
+ public static function factory ($ name , array $ options = null )
25
+ {
26
+ $ class = 'OAuth2_Provider_ ' .ucfirst ($ name );
27
+ return new $ class ($ options );
28
+ }
29
+
14
30
/**
15
31
* @var string provider name
16
32
*/
@@ -21,11 +37,26 @@ abstract class OAuth2_Provider {
21
37
*/
22
38
public $ uid_key = 'uid ' ;
23
39
40
+ /**
41
+ * @var string scope separator, most use "," but some like Google are spaces
42
+ */
43
+ public $ scope_seperator = ', ' ;
44
+
45
+ /**
46
+ * @var string additional request parameters to be used for remote requests
47
+ */
48
+ public $ callback = null ;
49
+
24
50
/**
25
51
* @var array additional request parameters to be used for remote requests
26
52
*/
27
53
protected $ params = array ();
28
54
55
+ /**
56
+ * @var string the method to use when requesting tokens
57
+ */
58
+ protected $ method = 'GET ' ;
59
+
29
60
/**
30
61
* Overloads default class properties from the options.
31
62
*
@@ -34,21 +65,26 @@ abstract class OAuth2_Provider {
34
65
* @param array provider options
35
66
* @return void
36
67
*/
37
- public function __construct (array $ options = NULL )
68
+ public function __construct (array $ options = array () )
38
69
{
39
70
if ( ! $ this ->name )
40
71
{
41
72
// Attempt to guess the name from the class name
42
73
$ this ->name = strtolower (substr (get_class ($ this ), strlen ('OAuth2_Provider_ ' )));
43
74
}
44
-
45
- foreach ( $ options as $ key => $ val )
75
+
76
+ if ( empty ( $ options[ ' id ' ]) )
46
77
{
47
- $ this ->{ $ key } = $ val ;
78
+ throw new Exception ( ' Required option not provided: id ' ) ;
48
79
}
80
+
81
+ $ this ->client_id = $ options ['id ' ];
49
82
50
- // Set a default, which will be used if none are provided pre-request
51
- $ this ->redirect_uri = get_instance ()->config ->site_url (get_instance ()->uri ->uri_string ());
83
+ isset ($ options ['callback ' ]) and $ this ->callback = $ options ['callback ' ];
84
+ isset ($ options ['secret ' ]) and $ this ->client_secret = $ options ['secret ' ];
85
+ isset ($ options ['scope ' ]) and $ this ->scope = $ options ['scope ' ];
86
+
87
+ $ this ->redirect_uri = site_url (get_instance ()->uri ->uri_string ());
52
88
}
53
89
54
90
/**
@@ -90,17 +126,15 @@ public function authorize($options = array())
90
126
{
91
127
$ state = md5 (uniqid (rand (), TRUE ));
92
128
get_instance ()->session ->set_userdata ('state ' , $ state );
93
-
94
- $ params = array (
95
- 'client_id ' => $ this ->client_id ,
96
- 'redirect_uri ' => isset ($ options ['redirect_uri ' ]) ? $ options ['redirect_uri ' ] : $ this ->redirect_uri ,
97
- 'state ' => $ state ,
98
- 'scope ' => $ this ->scope ,
99
- 'response_type ' => 'code ' , # required for Windows Live
100
- );
101
-
102
- $ url = $ this ->url_authorize ().'? ' .http_build_query ($ params );
103
-
129
+
130
+ $ url = $ this ->url_authorize ().'? ' .http_build_query (array (
131
+ 'client_id ' => $ this ->client_id ,
132
+ 'redirect_uri ' => isset ($ options ['redirect_uri ' ]) ? $ options ['redirect_uri ' ] : $ this ->redirect_uri ,
133
+ 'state ' => $ state ,
134
+ 'scope ' => is_array ($ this ->scope ) ? implode ($ this ->scope_seperator , $ this ->scope ) : $ this ->scope ,
135
+ 'response_type ' => 'code ' ,
136
+ ));
137
+
104
138
redirect ($ url );
105
139
}
106
140
@@ -110,39 +144,78 @@ public function authorize($options = array())
110
144
* @param string The access code
111
145
* @return object Success or failure along with the response details
112
146
*/
113
- public function access ($ code )
147
+ public function access ($ code, $ options = array () )
114
148
{
115
149
$ params = array (
116
- 'client_id ' => $ this ->client_id ,
117
- 'redirect_uri ' => isset ($ options ['redirect_uri ' ]) ? $ options ['redirect_uri ' ] : $ this ->redirect_uri ,
150
+ 'client_id ' => $ this ->client_id ,
118
151
'client_secret ' => $ this ->client_secret ,
119
- 'code ' => $ code ,
120
- 'grant_type ' => 'authorization_code ' , # required for Windows Live
152
+ 'grant_type ' => isset ($ options ['grant_type ' ]) ? $ options ['grant_type ' ] : 'authorization_code ' ,
121
153
);
122
-
123
- $ url = $ this ->url_access_token ().'? ' .http_build_query ($ params );
124
-
125
- $ response = file_get_contents ($ url );
126
154
127
- $ params = null ;
155
+ switch ($ params ['grant_type ' ])
156
+ {
157
+ case 'authorization_code ' :
158
+ $ params ['code ' ] = $ code ;
159
+ $ params ['redirect_uri ' ] = isset ($ options ['redirect_uri ' ]) ? $ options ['redirect_uri ' ] : $ this ->redirect_uri ;
160
+ break ;
161
+
162
+ case 'refresh_token ' :
163
+ $ params ['refresh_token ' ] = $ code ;
164
+ break ;
165
+ }
166
+
167
+ $ response = null ;
168
+ $ url = $ this ->url_access_token ();
128
169
129
- // TODO: This could be moved to a provider method to reduce provider specific awareness
130
- switch ($ this ->name )
170
+ switch ($ this ->method )
131
171
{
132
- case 'windowslive ' :
133
- $ params = json_decode ($ response , true );
172
+ case 'GET ' :
173
+
174
+ // Need to switch to Request library, but need to test it on one that works
175
+ $ url .= '? ' .http_build_query ($ params );
176
+ $ response = file_get_contents ($ url );
177
+
178
+ parse_str ($ response , $ return );
179
+
180
+ break ;
181
+
182
+ case 'POST ' :
183
+
184
+ $ postdata = http_build_query ($ params );
185
+ $ opts = array (
186
+ 'http ' => array (
187
+ 'method ' => 'POST ' ,
188
+ 'header ' => 'Content-type: application/x-www-form-urlencoded ' ,
189
+ 'content ' => $ postdata
190
+ )
191
+ );
192
+ $ context = stream_context_create ($ opts );
193
+ $ response = file_get_contents ($ url , false , $ context );
194
+
195
+ $ return = get_object_vars (json_decode ($ response ));
196
+
134
197
break ;
135
198
136
199
default :
137
- parse_str ( $ response , $ params );
200
+ throw new OutOfBoundsException ( " Method ' { $ this -> method } ' must be either GET or POST " );
138
201
}
139
202
140
- if (isset ($ params ['error ' ]))
203
+ if (isset ($ return ['error ' ]))
141
204
{
142
- throw new OAuth2_Exception ($ params );
205
+ throw new OAuth2_Exception ($ return );
206
+ }
207
+
208
+ switch ($ params ['grant_type ' ])
209
+ {
210
+ case 'authorization_code ' :
211
+ return OAuth2_Token::factory ('access ' , $ return );
212
+ break ;
213
+
214
+ case 'refresh_token ' :
215
+ return OAuth2_Token::factory ('refresh ' , $ return );
216
+ break ;
143
217
}
144
218
145
- return $ params ;
146
219
}
147
220
148
221
}
0 commit comments