4 * An implementation of the OpenID Provider Authentication Policy
8 * http://openid.net/developers/specs/
11 require_once "Auth/OpenID/Extension.php";
13 define('Auth_OpenID_PAPE_NS_URI',
14 "http://specs.openid.net/extensions/pape/1.0");
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');
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$/');
26 * A Provider Authentication Policy request, sent from a relying party
29 * preferred_auth_policies: The authentication policies that
30 * the relying party prefers
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
35 class Auth_OpenID_PAPE_Request extends Auth_OpenID_Extension {
37 var $ns_alias = 'pape';
38 var $ns_uri = Auth_OpenID_PAPE_NS_URI;
40 function Auth_OpenID_PAPE_Request($preferred_auth_policies=null,
43 if ($preferred_auth_policies === null) {
44 $preferred_auth_policies = array();
47 $this->preferred_auth_policies = $preferred_auth_policies;
48 $this->max_auth_age = $max_auth_age;
52 * Add an acceptable authentication policy URI to this request
54 * This method is intended to be used by the relying party to add
55 * acceptable authentication types to the request.
57 * policy_uri: The identifier for the preferred type of
60 function addPolicyURI($policy_uri)
62 if (!in_array($policy_uri, $this->preferred_auth_policies)) {
63 $this->preferred_auth_policies[] = $policy_uri;
67 function getExtensionArgs()
70 'preferred_auth_policies' =>
71 implode(' ', $this->preferred_auth_policies)
74 if ($this->max_auth_age !== null) {
75 $ns_args['max_auth_age'] = strval($this->max_auth_age);
82 * Instantiate a Request object from the arguments in a checkid_*
85 static function fromOpenIDRequest($request)
87 $obj = new Auth_OpenID_PAPE_Request();
88 $args = $request->message->getArgs(Auth_OpenID_PAPE_NS_URI);
90 if ($args === null || $args === array()) {
94 $obj->parseExtensionArgs($args);
99 * Set the state of this request to be that expressed in these
102 * @param args: The PAPE arguments without a namespace
104 function parseExtensionArgs($args)
106 // preferred_auth_policies is a space-separated list of policy
108 $this->preferred_auth_policies = array();
110 $policies_str = Auth_OpenID::arrayGet($args, 'preferred_auth_policies');
112 foreach (explode(' ', $policies_str) as $uri) {
113 if (!in_array($uri, $this->preferred_auth_policies)) {
114 $this->preferred_auth_policies[] = $uri;
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);
124 $this->max_auth_age = null;
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.
133 * @param supported_types: A sequence of authentication policy
134 * type URIs that are supported by a provider
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.
142 function preferredTypes($supported_types)
146 foreach ($supported_types as $st) {
147 if (in_array($st, $this->preferred_auth_policies)) {
156 * A Provider Authentication Policy response, sent from a provider to
159 class Auth_OpenID_PAPE_Response extends Auth_OpenID_Extension {
161 var $ns_alias = 'pape';
162 var $ns_uri = Auth_OpenID_PAPE_NS_URI;
164 function Auth_OpenID_PAPE_Response($auth_policies=null, $auth_time=null,
165 $nist_auth_level=null)
167 if ($auth_policies) {
168 $this->auth_policies = $auth_policies;
170 $this->auth_policies = array();
173 $this->auth_time = $auth_time;
174 $this->nist_auth_level = $nist_auth_level;
178 * Add a authentication policy to this response
180 * This method is intended to be used by the provider to add a
181 * policy that the provider conformed to when authenticating the
184 * @param policy_uri: The identifier for the preferred type of
187 function addPolicyURI($policy_uri)
189 if (!in_array($policy_uri, $this->auth_policies)) {
190 $this->auth_policies[] = $policy_uri;
195 * Create an Auth_OpenID_PAPE_Response object from a successful
196 * OpenID library response.
198 * @param success_response $success_response A SuccessResponse
199 * from Auth_OpenID_Consumer::complete()
201 * @returns: A provider authentication policy response from the
202 * data that was supplied with the id_res response.
204 static function fromSuccessResponse($success_response)
206 $obj = new Auth_OpenID_PAPE_Response();
208 // PAPE requires that the args be signed.
209 $args = $success_response->getSignedNS(Auth_OpenID_PAPE_NS_URI);
211 if ($args === null || $args === array()) {
215 $result = $obj->parseExtensionArgs($args);
217 if ($result === false) {
225 * Parse the provider authentication policy arguments into the
226 * internal state of this object
228 * @param args: unqualified provider authentication policy
231 * @param strict: Whether to return false when bad data is
234 * @return null The data is parsed into the internal fields of
237 function parseExtensionArgs($args, $strict=false)
239 $policies_str = Auth_OpenID::arrayGet($args, 'auth_policies');
240 if ($policies_str && $policies_str != "none") {
241 $this->auth_policies = explode(" ", $policies_str);
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);
248 if ($nist_level === false) {
256 if (0 <= $nist_level && $nist_level < 5) {
257 $this->nist_auth_level = $nist_level;
258 } else if ($strict) {
263 $auth_time = Auth_OpenID::arrayGet($args, 'auth_time');
264 if ($auth_time !== null) {
265 if (preg_match(PAPE_TIME_VALIDATOR, $auth_time)) {
266 $this->auth_time = $auth_time;
267 } else if ($strict) {
273 function getExtensionArgs()
276 if (count($this->auth_policies) > 0) {
277 $ns_args['auth_policies'] = implode(' ', $this->auth_policies);
279 $ns_args['auth_policies'] = 'none';
282 if ($this->nist_auth_level !== null) {
283 if (!in_array($this->nist_auth_level, range(0, 4), true)) {
286 $ns_args['nist_auth_level'] = strval($this->nist_auth_level);
289 if ($this->auth_time !== null) {
290 if (!preg_match(PAPE_TIME_VALIDATOR, $this->auth_time)) {
294 $ns_args['auth_time'] = $this->auth_time;