final move of files
[web.mtrack] / Auth / OpenID / PAPE.php
1 <?php
2
3 /**
4  * An implementation of the OpenID Provider Authentication Policy
5  *  Extension 1.0
6  *
7  * See:
8  * http://openid.net/developers/specs/
9  */
10
11 require_once "Auth/OpenID/Extension.php";
12
13 define('Auth_OpenID_PAPE_NS_URI',
14        "http://specs.openid.net/extensions/pape/1.0");
15
16 define('PAPE_AUTH_MULTI_FACTOR_PHYSICAL',
17        'http://schemas.openid.net/pape/policies/2007/06/multi-factor-physical');
18 define('PAPE_AUTH_MULTI_FACTOR',
19        'http://schemas.openid.net/pape/policies/2007/06/multi-factor');
20 define('PAPE_AUTH_PHISHING_RESISTANT',
21        'http://schemas.openid.net/pape/policies/2007/06/phishing-resistant');
22
23 define('PAPE_TIME_VALIDATOR',
24        '^[0-9]{4,4}-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9]Z$');
25 /**
26  * A Provider Authentication Policy request, sent from a relying party
27  * to a provider
28  *
29  * preferred_auth_policies: The authentication policies that
30  * the relying party prefers
31  *
32  * max_auth_age: The maximum time, in seconds, that the relying party
33  * wants to allow to have elapsed before the user must re-authenticate
34  */
35 class Auth_OpenID_PAPE_Request extends Auth_OpenID_Extension {
36
37     var $ns_alias = 'pape';
38     var $ns_uri = Auth_OpenID_PAPE_NS_URI;
39
40     function Auth_OpenID_PAPE_Request($preferred_auth_policies=null,
41                                       $max_auth_age=null)
42     {
43         if ($preferred_auth_policies === null) {
44             $preferred_auth_policies = array();
45         }
46
47         $this->preferred_auth_policies = $preferred_auth_policies;
48         $this->max_auth_age = $max_auth_age;
49     }
50
51     /**
52      * Add an acceptable authentication policy URI to this request
53      *
54      * This method is intended to be used by the relying party to add
55      * acceptable authentication types to the request.
56      *
57      * policy_uri: The identifier for the preferred type of
58      * authentication.
59      */
60     function addPolicyURI($policy_uri)
61     {
62         if (!in_array($policy_uri, $this->preferred_auth_policies)) {
63             $this->preferred_auth_policies[] = $policy_uri;
64         }
65     }
66
67     function getExtensionArgs()
68     {
69         $ns_args = array(
70                          'preferred_auth_policies' =>
71                            implode(' ', $this->preferred_auth_policies)
72                          );
73
74         if ($this->max_auth_age !== null) {
75             $ns_args['max_auth_age'] = strval($this->max_auth_age);
76         }
77
78         return $ns_args;
79     }
80
81     /**
82      * Instantiate a Request object from the arguments in a checkid_*
83      * OpenID message
84      */
85     function fromOpenIDRequest($request)
86     {
87         $obj = new Auth_OpenID_PAPE_Request();
88         $args = $request->message->getArgs(Auth_OpenID_PAPE_NS_URI);
89
90         if ($args === null || $args === array()) {
91             return null;
92         }
93
94         $obj->parseExtensionArgs($args);
95         return $obj;
96     }
97
98     /**
99      * Set the state of this request to be that expressed in these
100      * PAPE arguments
101      *
102      * @param args: The PAPE arguments without a namespace
103      */
104     function parseExtensionArgs($args)
105     {
106         // preferred_auth_policies is a space-separated list of policy
107         // URIs
108         $this->preferred_auth_policies = array();
109
110         $policies_str = Auth_OpenID::arrayGet($args, 'preferred_auth_policies');
111         if ($policies_str) {
112             foreach (explode(' ', $policies_str) as $uri) {
113                 if (!in_array($uri, $this->preferred_auth_policies)) {
114                     $this->preferred_auth_policies[] = $uri;
115                 }
116             }
117         }
118
119         // max_auth_age is base-10 integer number of seconds
120         $max_auth_age_str = Auth_OpenID::arrayGet($args, 'max_auth_age');
121         if ($max_auth_age_str) {
122             $this->max_auth_age = Auth_OpenID::intval($max_auth_age_str);
123         } else {
124             $this->max_auth_age = null;
125         }
126     }
127
128     /**
129      * Given a list of authentication policy URIs that a provider
130      * supports, this method returns the subsequence of those types
131      * that are preferred by the relying party.
132      *
133      * @param supported_types: A sequence of authentication policy
134      * type URIs that are supported by a provider
135      *
136      * @return array The sub-sequence of the supported types that are
137      * preferred by the relying party. This list will be ordered in
138      * the order that the types appear in the supported_types
139      * sequence, and may be empty if the provider does not prefer any
140      * of the supported authentication types.
141      */
142     function preferredTypes($supported_types)
143     {
144         $result = array();
145
146         foreach ($supported_types as $st) {
147             if (in_array($st, $this->preferred_auth_policies)) {
148                 $result[] = $st;
149             }
150         }
151         return $result;
152     }
153 }
154
155 /**
156  * A Provider Authentication Policy response, sent from a provider to
157  * a relying party
158  */
159 class Auth_OpenID_PAPE_Response extends Auth_OpenID_Extension {
160
161     var $ns_alias = 'pape';
162     var $ns_uri = Auth_OpenID_PAPE_NS_URI;
163
164     function Auth_OpenID_PAPE_Response($auth_policies=null, $auth_time=null,
165                                        $nist_auth_level=null)
166     {
167         if ($auth_policies) {
168             $this->auth_policies = $auth_policies;
169         } else {
170             $this->auth_policies = array();
171         }
172
173         $this->auth_time = $auth_time;
174         $this->nist_auth_level = $nist_auth_level;
175     }
176
177     /**
178      * Add a authentication policy to this response
179      *
180      * This method is intended to be used by the provider to add a
181      * policy that the provider conformed to when authenticating the
182      * user.
183      *
184      * @param policy_uri: The identifier for the preferred type of
185      * authentication.
186      */
187     function addPolicyURI($policy_uri)
188     {
189         if (!in_array($policy_uri, $this->auth_policies)) {
190             $this->auth_policies[] = $policy_uri;
191         }
192     }
193
194     /**
195      * Create an Auth_OpenID_PAPE_Response object from a successful
196      * OpenID library response.
197      *
198      * @param success_response $success_response A SuccessResponse
199      * from Auth_OpenID_Consumer::complete()
200      *
201      * @returns: A provider authentication policy response from the
202      * data that was supplied with the id_res response.
203      */
204     function fromSuccessResponse($success_response)
205     {
206         $obj = new Auth_OpenID_PAPE_Response();
207
208         // PAPE requires that the args be signed.
209         $args = $success_response->getSignedNS(Auth_OpenID_PAPE_NS_URI);
210
211         if ($args === null || $args === array()) {
212             return null;
213         }
214
215         $result = $obj->parseExtensionArgs($args);
216
217         if ($result === false) {
218             return null;
219         } else {
220             return $obj;
221         }
222     }
223
224     /**
225      * Parse the provider authentication policy arguments into the
226      *  internal state of this object
227      *
228      * @param args: unqualified provider authentication policy
229      * arguments
230      *
231      * @param strict: Whether to return false when bad data is
232      * encountered
233      *
234      * @return null The data is parsed into the internal fields of
235      * this object.
236     */
237     function parseExtensionArgs($args, $strict=false)
238     {
239         $policies_str = Auth_OpenID::arrayGet($args, 'auth_policies');
240         if ($policies_str && $policies_str != "none") {
241             $this->auth_policies = explode(" ", $policies_str);
242         }
243
244         $nist_level_str = Auth_OpenID::arrayGet($args, 'nist_auth_level');
245         if ($nist_level_str !== null) {
246             $nist_level = Auth_OpenID::intval($nist_level_str);
247
248             if ($nist_level === false) {
249                 if ($strict) {
250                     return false;
251                 } else {
252                     $nist_level = null;
253                 }
254             }
255
256             if (0 <= $nist_level && $nist_level < 5) {
257                 $this->nist_auth_level = $nist_level;
258             } else if ($strict) {
259                 return false;
260             }
261         }
262
263         $auth_time = Auth_OpenID::arrayGet($args, 'auth_time');
264         if ($auth_time !== null) {
265             if (ereg(PAPE_TIME_VALIDATOR, $auth_time)) {
266                 $this->auth_time = $auth_time;
267             } else if ($strict) {
268                 return false;
269             }
270         }
271     }
272
273     function getExtensionArgs()
274     {
275         $ns_args = array();
276         if (count($this->auth_policies) > 0) {
277             $ns_args['auth_policies'] = implode(' ', $this->auth_policies);
278         } else {
279             $ns_args['auth_policies'] = 'none';
280         }
281
282         if ($this->nist_auth_level !== null) {
283             if (!in_array($this->nist_auth_level, range(0, 4), true)) {
284                 return false;
285             }
286             $ns_args['nist_auth_level'] = strval($this->nist_auth_level);
287         }
288
289         if ($this->auth_time !== null) {
290             if (!ereg(PAPE_TIME_VALIDATOR, $this->auth_time)) {
291                 return false;
292             }
293
294             $ns_args['auth_time'] = $this->auth_time;
295         }
296
297         return $ns_args;
298     }
299 }
300
301 ?>