PageRenderTime 59ms CodeModel.GetById 29ms RepoModel.GetById 1ms app.codeStats 0ms

/Auth/OpenID/PAPE.php

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