1 | <?php |
---|
2 | /*! |
---|
3 | * HybridAuth |
---|
4 | * http://hybridauth.sourceforge.net | http://github.com/hybridauth/hybridauth |
---|
5 | * (c) 2009-2012, HybridAuth authors | http://hybridauth.sourceforge.net/licenses.html |
---|
6 | */ |
---|
7 | |
---|
8 | /** |
---|
9 | * To implement an OAuth 2 based service provider, Hybrid_Provider_Model_OAuth2 |
---|
10 | * can be used to save the hassle of the authentication flow. |
---|
11 | * |
---|
12 | * Each class that inherit from Hybrid_Provider_Model_OAuth2 have to implemenent |
---|
13 | * at least 2 methods: |
---|
14 | * Hybrid_Providers_{provider_name}::initialize() to setup the provider api end-points urls |
---|
15 | * Hybrid_Providers_{provider_name}::getUserProfile() to grab the user profile |
---|
16 | * |
---|
17 | * Hybrid_Provider_Model_OAuth2 use OAuth2Client v0.1 which can be found on |
---|
18 | * Hybrid/thirdparty/OAuth/OAuth2Client.php |
---|
19 | */ |
---|
20 | class Hybrid_Provider_Model_OAuth2 extends Hybrid_Provider_Model |
---|
21 | { |
---|
22 | // default permissions |
---|
23 | public $scope = ""; |
---|
24 | |
---|
25 | /** |
---|
26 | * try to get the error message from provider api |
---|
27 | */ |
---|
28 | function errorMessageByStatus( $code = null ) { |
---|
29 | $http_status_codes = ARRAY( |
---|
30 | 200 => "OK: Success!", |
---|
31 | 304 => "Not Modified: There was no new data to return.", |
---|
32 | 400 => "Bad Request: The request was invalid.", |
---|
33 | 401 => "Unauthorized.", |
---|
34 | 403 => "Forbidden: The request is understood, but it has been refused.", |
---|
35 | 404 => "Not Found: The URI requested is invalid or the resource requested does not exists.", |
---|
36 | 406 => "Not Acceptable.", |
---|
37 | 500 => "Internal Server Error: Something is broken.", |
---|
38 | 502 => "Bad Gateway.", |
---|
39 | 503 => "Service Unavailable." |
---|
40 | ); |
---|
41 | |
---|
42 | if( ! $code && $this->api ) |
---|
43 | $code = $this->api->http_code; |
---|
44 | |
---|
45 | if( isset( $http_status_codes[ $code ] ) ) |
---|
46 | return $code . " " . $http_status_codes[ $code ]; |
---|
47 | } |
---|
48 | |
---|
49 | // -------------------------------------------------------------------- |
---|
50 | |
---|
51 | /** |
---|
52 | * adapter initializer |
---|
53 | */ |
---|
54 | function initialize() |
---|
55 | { |
---|
56 | if ( ! $this->config["keys"]["id"] || ! $this->config["keys"]["secret"] ){ |
---|
57 | throw new Exception( "Your application id and secret are required in order to connect to {$this->providerId}.", 4 ); |
---|
58 | } |
---|
59 | |
---|
60 | // override requested scope |
---|
61 | if( isset( $this->config["scope"] ) && ! empty( $this->config["scope"] ) ){ |
---|
62 | $this->scope = $this->config["scope"]; |
---|
63 | } |
---|
64 | |
---|
65 | // include OAuth2 client |
---|
66 | require_once Hybrid_Auth::$config["path_libraries"] . "OAuth/OAuth2Client.php"; |
---|
67 | |
---|
68 | // create a new OAuth2 client instance |
---|
69 | $this->api = new OAuth2Client( $this->config["keys"]["id"], $this->config["keys"]["secret"], $this->endpoint ); |
---|
70 | |
---|
71 | // If we have an access token, set it |
---|
72 | if( $this->token( "access_token" ) ){ |
---|
73 | $this->api->access_token = $this->token( "access_token" ); |
---|
74 | $this->api->refresh_token = $this->token( "refresh_token" ); |
---|
75 | $this->api->access_token_expires_in = $this->token( "expires_in" ); |
---|
76 | $this->api->access_token_expires_at = $this->token( "expires_at" ); |
---|
77 | } |
---|
78 | |
---|
79 | // Set curl proxy if exist |
---|
80 | if( isset( Hybrid_Auth::$config["proxy"] ) ){ |
---|
81 | $this->api->curl_proxy = Hybrid_Auth::$config["proxy"]; |
---|
82 | } |
---|
83 | } |
---|
84 | |
---|
85 | // -------------------------------------------------------------------- |
---|
86 | |
---|
87 | /** |
---|
88 | * begin login step |
---|
89 | */ |
---|
90 | function loginBegin() |
---|
91 | { |
---|
92 | // redirect the user to the provider authentication url |
---|
93 | Hybrid_Auth::redirect( $this->api->authorizeUrl( array( "scope" => $this->scope ) ) ); |
---|
94 | } |
---|
95 | |
---|
96 | // -------------------------------------------------------------------- |
---|
97 | |
---|
98 | /** |
---|
99 | * finish login step |
---|
100 | */ |
---|
101 | function loginFinish() |
---|
102 | { |
---|
103 | $error = (array_key_exists('error',$_REQUEST))?$_REQUEST['error']:""; |
---|
104 | |
---|
105 | // check for errors |
---|
106 | if ( $error ){ |
---|
107 | throw new Exception( "Authentication failed! {$this->providerId} returned an error: $error", 5 ); |
---|
108 | } |
---|
109 | |
---|
110 | // try to authenicate user |
---|
111 | $code = (array_key_exists('code',$_REQUEST))?$_REQUEST['code']:""; |
---|
112 | |
---|
113 | try{ |
---|
114 | $this->api->authenticate( $code ); |
---|
115 | } |
---|
116 | catch( Exception $e ){ |
---|
117 | throw new Exception( "User profile request failed! {$this->providerId} returned an error: $e", 6 ); |
---|
118 | } |
---|
119 | |
---|
120 | // check if authenticated |
---|
121 | if ( ! $this->api->access_token ){ |
---|
122 | throw new Exception( "Authentication failed! {$this->providerId} returned an invalid access token.", 5 ); |
---|
123 | } |
---|
124 | |
---|
125 | // store tokens |
---|
126 | $this->token( "access_token" , $this->api->access_token ); |
---|
127 | $this->token( "refresh_token", $this->api->refresh_token ); |
---|
128 | $this->token( "expires_in" , $this->api->access_token_expires_in ); |
---|
129 | $this->token( "expires_at" , $this->api->access_token_expires_at ); |
---|
130 | |
---|
131 | // set user connected locally |
---|
132 | $this->setUserConnected(); |
---|
133 | } |
---|
134 | |
---|
135 | function refreshToken() |
---|
136 | { |
---|
137 | // have an access token? |
---|
138 | if( $this->api->access_token ){ |
---|
139 | |
---|
140 | // have to refresh? |
---|
141 | if( $this->api->refresh_token && $this->api->access_token_expires_at ){ |
---|
142 | |
---|
143 | // expired? |
---|
144 | if( $this->api->access_token_expires_at <= time() ){ |
---|
145 | $response = $this->api->refreshToken( array( "refresh_token" => $this->api->refresh_token ) ); |
---|
146 | |
---|
147 | if( ! isset( $response->access_token ) || ! $response->access_token ){ |
---|
148 | // set the user as disconnected at this point and throw an exception |
---|
149 | $this->setUserUnconnected(); |
---|
150 | |
---|
151 | throw new Exception( "The Authorization Service has return an invalid response while requesting a new access token. " . (string) $response->error ); |
---|
152 | } |
---|
153 | |
---|
154 | // set new access_token |
---|
155 | $this->api->access_token = $response->access_token; |
---|
156 | |
---|
157 | if( isset( $response->refresh_token ) ) |
---|
158 | $this->api->refresh_token = $response->refresh_token; |
---|
159 | |
---|
160 | if( isset( $response->expires_in ) ){ |
---|
161 | $this->api->access_token_expires_in = $response->expires_in; |
---|
162 | |
---|
163 | // even given by some idp, we should calculate this |
---|
164 | $this->api->access_token_expires_at = time() + $response->expires_in; |
---|
165 | } |
---|
166 | } |
---|
167 | } |
---|
168 | |
---|
169 | // re store tokens |
---|
170 | $this->token( "access_token" , $this->api->access_token ); |
---|
171 | $this->token( "refresh_token", $this->api->refresh_token ); |
---|
172 | $this->token( "expires_in" , $this->api->access_token_expires_in ); |
---|
173 | $this->token( "expires_at" , $this->api->access_token_expires_at ); |
---|
174 | } |
---|
175 | } |
---|
176 | } |
---|