Package openid :: Package extensions :: Package draft :: Module pape2
[frames] | no frames]

Source Code for Module openid.extensions.draft.pape2

  1  """An implementation of the OpenID Provider Authentication Policy 
  2  Extension 1.0 
  3   
  4  @see: http://openid.net/developers/specs/ 
  5   
  6  @since: 2.1.0 
  7  """ 
  8   
  9  __all__ = [ 
 10      'Request', 
 11      'Response', 
 12      'ns_uri', 
 13      'AUTH_PHISHING_RESISTANT', 
 14      'AUTH_MULTI_FACTOR', 
 15      'AUTH_MULTI_FACTOR_PHYSICAL', 
 16      ] 
 17   
 18  from openid.extension import Extension 
 19  import re 
 20   
 21  ns_uri = "http://specs.openid.net/extensions/pape/1.0" 
 22   
 23  AUTH_MULTI_FACTOR_PHYSICAL = \ 
 24      'http://schemas.openid.net/pape/policies/2007/06/multi-factor-physical' 
 25  AUTH_MULTI_FACTOR = \ 
 26      'http://schemas.openid.net/pape/policies/2007/06/multi-factor' 
 27  AUTH_PHISHING_RESISTANT = \ 
 28      'http://schemas.openid.net/pape/policies/2007/06/phishing-resistant' 
 29   
 30  TIME_VALIDATOR = re.compile('^\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\dZ$') 
 31   
32 -class Request(Extension):
33 """A Provider Authentication Policy request, sent from a relying 34 party to a provider 35 36 @ivar preferred_auth_policies: The authentication policies that 37 the relying party prefers 38 @type preferred_auth_policies: [str] 39 40 @ivar max_auth_age: The maximum time, in seconds, that the relying 41 party wants to allow to have elapsed before the user must 42 re-authenticate 43 @type max_auth_age: int or NoneType 44 """ 45 46 ns_alias = 'pape' 47
48 - def __init__(self, preferred_auth_policies=None, max_auth_age=None):
49 super(Request, self).__init__() 50 if not preferred_auth_policies: 51 preferred_auth_policies = [] 52 53 self.preferred_auth_policies = preferred_auth_policies 54 self.max_auth_age = max_auth_age
55
56 - def __nonzero__(self):
57 return bool(self.preferred_auth_policies or 58 self.max_auth_age is not None)
59
60 - def addPolicyURI(self, policy_uri):
61 """Add an acceptable authentication policy URI to this request 62 63 This method is intended to be used by the relying party to add 64 acceptable authentication types to the request. 65 66 @param policy_uri: The identifier for the preferred type of 67 authentication. 68 @see: http://openid.net/specs/openid-provider-authentication-policy-extension-1_0-01.html#auth_policies 69 """ 70 if policy_uri not in self.preferred_auth_policies: 71 self.preferred_auth_policies.append(policy_uri)
72
73 - def getExtensionArgs(self):
74 """@see: C{L{Extension.getExtensionArgs}} 75 """ 76 ns_args = { 77 'preferred_auth_policies':' '.join(self.preferred_auth_policies) 78 } 79 80 if self.max_auth_age is not None: 81 ns_args['max_auth_age'] = str(self.max_auth_age) 82 83 return ns_args
84
85 - def fromOpenIDRequest(cls, request):
86 """Instantiate a Request object from the arguments in a 87 C{checkid_*} OpenID message 88 """ 89 self = cls() 90 args = request.message.getArgs(self.ns_uri) 91 92 if args == {}: 93 return None 94 95 self.parseExtensionArgs(args) 96 return self
97 98 fromOpenIDRequest = classmethod(fromOpenIDRequest) 99
100 - def parseExtensionArgs(self, args):
101 """Set the state of this request to be that expressed in these 102 PAPE arguments 103 104 @param args: The PAPE arguments without a namespace 105 106 @rtype: None 107 108 @raises ValueError: When the max_auth_age is not parseable as 109 an integer 110 """ 111 112 # preferred_auth_policies is a space-separated list of policy URIs 113 self.preferred_auth_policies = [] 114 115 policies_str = args.get('preferred_auth_policies') 116 if policies_str: 117 for uri in policies_str.split(' '): 118 if uri not in self.preferred_auth_policies: 119 self.preferred_auth_policies.append(uri) 120 121 # max_auth_age is base-10 integer number of seconds 122 max_auth_age_str = args.get('max_auth_age') 123 self.max_auth_age = None 124 125 if max_auth_age_str: 126 try: 127 self.max_auth_age = int(max_auth_age_str) 128 except ValueError: 129 pass
130
131 - def preferredTypes(self, supported_types):
132 """Given a list of authentication policy URIs that a provider 133 supports, this method returns the subsequence of those types 134 that are preferred by the relying party. 135 136 @param supported_types: A sequence of authentication policy 137 type URIs that are supported by a provider 138 139 @returns: The sub-sequence of the supported types that are 140 preferred by the relying party. This list will be ordered 141 in the order that the types appear in the supported_types 142 sequence, and may be empty if the provider does not prefer 143 any of the supported authentication types. 144 145 @returntype: [str] 146 """ 147 return filter(self.preferred_auth_policies.__contains__, 148 supported_types)
149 150 Request.ns_uri = ns_uri 151 152
153 -class Response(Extension):
154 """A Provider Authentication Policy response, sent from a provider 155 to a relying party 156 """ 157 158 ns_alias = 'pape' 159
160 - def __init__(self, auth_policies=None, auth_time=None, 161 nist_auth_level=None):
162 super(Response, self).__init__() 163 if auth_policies: 164 self.auth_policies = auth_policies 165 else: 166 self.auth_policies = [] 167 168 self.auth_time = auth_time 169 self.nist_auth_level = nist_auth_level
170
171 - def addPolicyURI(self, policy_uri):
172 """Add a authentication policy to this response 173 174 This method is intended to be used by the provider to add a 175 policy that the provider conformed to when authenticating the user. 176 177 @param policy_uri: The identifier for the preferred type of 178 authentication. 179 @see: http://openid.net/specs/openid-provider-authentication-policy-extension-1_0-01.html#auth_policies 180 """ 181 if policy_uri not in self.auth_policies: 182 self.auth_policies.append(policy_uri)
183
184 - def fromSuccessResponse(cls, success_response):
185 """Create a C{L{Response}} object from a successful OpenID 186 library response 187 (C{L{openid.consumer.consumer.SuccessResponse}}) response 188 message 189 190 @param success_response: A SuccessResponse from consumer.complete() 191 @type success_response: C{L{openid.consumer.consumer.SuccessResponse}} 192 193 @rtype: Response or None 194 @returns: A provider authentication policy response from the 195 data that was supplied with the C{id_res} response or None 196 if the provider sent no signed PAPE response arguments. 197 """ 198 self = cls() 199 200 # PAPE requires that the args be signed. 201 args = success_response.getSignedNS(self.ns_uri) 202 203 # Only try to construct a PAPE response if the arguments were 204 # signed in the OpenID response. If not, return None. 205 if args is not None: 206 self.parseExtensionArgs(args) 207 return self 208 else: 209 return None
210
211 - def parseExtensionArgs(self, args, strict=False):
212 """Parse the provider authentication policy arguments into the 213 internal state of this object 214 215 @param args: unqualified provider authentication policy 216 arguments 217 218 @param strict: Whether to raise an exception when bad data is 219 encountered 220 221 @returns: None. The data is parsed into the internal fields of 222 this object. 223 """ 224 policies_str = args.get('auth_policies') 225 if policies_str and policies_str != 'none': 226 self.auth_policies = policies_str.split(' ') 227 228 nist_level_str = args.get('nist_auth_level') 229 if nist_level_str: 230 try: 231 nist_level = int(nist_level_str) 232 except ValueError: 233 if strict: 234 raise ValueError('nist_auth_level must be an integer between ' 235 'zero and four, inclusive') 236 else: 237 self.nist_auth_level = None 238 else: 239 if 0 <= nist_level < 5: 240 self.nist_auth_level = nist_level 241 242 auth_time = args.get('auth_time') 243 if auth_time: 244 if TIME_VALIDATOR.match(auth_time): 245 self.auth_time = auth_time 246 elif strict: 247 raise ValueError("auth_time must be in RFC3339 format")
248 249 fromSuccessResponse = classmethod(fromSuccessResponse) 250
251 - def getExtensionArgs(self):
252 """@see: C{L{Extension.getExtensionArgs}} 253 """ 254 if len(self.auth_policies) == 0: 255 ns_args = { 256 'auth_policies':'none', 257 } 258 else: 259 ns_args = { 260 'auth_policies':' '.join(self.auth_policies), 261 } 262 263 if self.nist_auth_level is not None: 264 if self.nist_auth_level not in range(0, 5): 265 raise ValueError('nist_auth_level must be an integer between ' 266 'zero and four, inclusive') 267 ns_args['nist_auth_level'] = str(self.nist_auth_level) 268 269 if self.auth_time is not None: 270 if not TIME_VALIDATOR.match(self.auth_time): 271 raise ValueError('auth_time must be in RFC3339 format') 272 273 ns_args['auth_time'] = self.auth_time 274 275 return ns_args
276 277 Response.ns_uri = ns_uri 278