|
Play Framework/Scala example source code file (OpenIDSpec.scala)
The OpenIDSpec.scala Play Framework example source code/* * Copyright (C) 2009-2013 Typesafe Inc. <http://www.typesafe.com> */ package play.api.libs.openid import org.specs2.mutable.Specification import scala.Predef._ import org.specs2.mock.Mockito import org.mockito._ import play.api.mvc.Request import play.api.http._ import play.api.http.Status._ import play.api.libs.openid.Errors.{BAD_RESPONSE, AUTH_ERROR} import scala.concurrent.Await import scala.concurrent.duration.Duration import java.util.concurrent.TimeUnit object OpenIDSpec extends Specification with Mockito { val claimedId = "http://example.com/openid?id=C123" val identity = "http://example.com/openid?id=C123&id" val defaultSigned = "op_endpoint,claimed_id,identity,return_to,response_nonce,assoc_handle" val dur = Duration(10, TimeUnit.SECONDS) // 9.1 Request parameters - http://openid.net/specs/openid-authentication-2_0.html#anchor27 def isValidOpenIDRequest(query:Params) = { query.get("openid.mode") must_== Some(Seq("checkid_setup")) query.get("openid.ns") must_== Some(Seq("http://specs.openid.net/auth/2.0")) } "OpenID" should { "initiate discovery" in { val ws = createMockWithValidOpDiscoveryAndVerification val openId = new OpenIDClient(ws) openId.redirectURL("http://example.com", "http://foo.bar.com/openid") there was one(ws.request).get() } "generate a valid redirectUrl" in { val ws = createMockWithValidOpDiscoveryAndVerification val openId = new OpenIDClient(ws) val redirectUrl = Await.result(openId.redirectURL("http://example.com", "http://foo.bar.com/returnto"), dur) val query = parseQueryString(redirectUrl) isValidOpenIDRequest(query) query.get("openid.return_to") must_== Some(Seq("http://foo.bar.com/returnto")) query.get("openid.realm") must beNone } "generate a valid redirectUrl with a proper required extended attributes request" in { val ws = createMockWithValidOpDiscoveryAndVerification val openId = new OpenIDClient(ws) val redirectUrl = Await.result(openId.redirectURL("http://example.com", "http://foo.bar.com/returnto", axRequired = Seq("email" -> "http://schema.openid.net/contact/email")), dur) val query = parseQueryString(redirectUrl) isValidOpenIDRequest(query) query.get("openid.ax.mode") must_== Some(Seq("fetch_request")) query.get("openid.ns.ax") must_== Some(Seq("http://openid.net/srv/ax/1.0")) query.get("openid.ax.required") must_== Some(Seq("email")) query.get("openid.ax.type.email") must_== Some(Seq("http://schema.openid.net/contact/email")) } "generate a valid redirectUrl with a proper 'if_available' extended attributes request" in { val ws = createMockWithValidOpDiscoveryAndVerification val openId = new OpenIDClient(ws) val redirectUrl = Await.result(openId.redirectURL("http://example.com", "http://foo.bar.com/returnto", axOptional = Seq("email" -> "http://schema.openid.net/contact/email")), dur) val query = parseQueryString(redirectUrl) isValidOpenIDRequest(query) query.get("openid.ax.mode") must_== Some(Seq("fetch_request")) query.get("openid.ns.ax") must_== Some(Seq("http://openid.net/srv/ax/1.0")) query.get("openid.ax.if_available") must_== Some(Seq("email")) query.get("openid.ax.type.email") must_== Some(Seq("http://schema.openid.net/contact/email")) } "generate a valid redirectUrl with a proper 'if_available' AND required extended attributes request" in { val ws = createMockWithValidOpDiscoveryAndVerification val openId = new OpenIDClient(ws) val redirectUrl = Await.result(openId.redirectURL("http://example.com", "http://foo.bar.com/returnto", axRequired = Seq("first" -> "http://axschema.org/namePerson/first"), axOptional = Seq("email" -> "http://schema.openid.net/contact/email")), dur) val query = parseQueryString(redirectUrl) isValidOpenIDRequest(query) query.get("openid.ax.mode") must_== Some(Seq("fetch_request")) query.get("openid.ns.ax") must_== Some(Seq("http://openid.net/srv/ax/1.0")) query.get("openid.ax.required") must_== Some(Seq("first")) query.get("openid.ax.type.first") must_== Some(Seq("http://axschema.org/namePerson/first")) query.get("openid.ax.if_available") must_== Some(Seq("email")) query.get("openid.ax.type.email") must_== Some(Seq("http://schema.openid.net/contact/email")) } "verify the response" in { val ws = createMockWithValidOpDiscoveryAndVerification val openId = new OpenIDClient(ws) val responseQueryString = openIdResponse val userInfo = Await.result(openId.verifiedId(setupMockRequest(responseQueryString)), dur) "the claimedId must be present" in { userInfo.id must be equalTo claimedId } val argument = ArgumentCaptor.forClass(classOf[Params]) "direct verification using a POST request was used" in { there was one(ws.request).post(argument.capture())(any[Writeable[Params]], any[ContentTypeOf[Params]]) val verificationQuery = argument.getValue "openid.mode was set to check_authentication" in { verificationQuery.get("openid.mode") must_== Some(Seq("check_authentication")) } "every query parameter apart from openid.mode is used in the verification request" in { (verificationQuery - "openid.mode") forall { case (key,value) => responseQueryString.get(key) == Some(value) } must beTrue } } } // 11.2 If the Claimed Identifier was not previously discovered by the Relying Party // (the "openid.identity" in the request was "http://specs.openid.net/auth/2.0/identifier_select" or a different Identifier, // or if the OP is sending an unsolicited positive assertion), the Relying Party MUST perform discovery on the // Claimed Identifier in the response to make sure that the OP is authorized to make assertions about the Claimed Identifier. "verify the response using discovery on the claimed Identifier" in { val ws = createMockWithValidOpDiscoveryAndVerification val openId = new OpenIDClient(ws) val spoofedEndpoint = "http://evilhackerendpoint.com" val responseQueryString = openIdResponse - "openid.op_endpoint" + ("openid.op_endpoint" -> Seq(spoofedEndpoint)) Await.result(openId.verifiedId(setupMockRequest(responseQueryString)), dur) "direct verification does not use the openid.op_endpoint that is part of the query string" in { ws.urls contains(spoofedEndpoint) must beFalse } "the endpoint is resolved using discovery on the claimed Id" in { ws.urls(0) must be equalTo claimedId } "use endpoint discovery and then direct verification" in { got { // Use discovery to resolve the endpoint one(ws.request).get() // Verify the response one(ws.request).post(any[Params])(any[Writeable[Params]], any[ContentTypeOf[Params]]) } } "use direct verification on the discovered endpoint" in { ws.urls(1) must be equalTo "https://www.google.com/a/example.com/o8/ud?be=o8" // From the mock XRDS } } "fail response verification if direct verification fails" in { val ws = new WSMock ws.response.status returns OK thenReturns OK ws.response.header(HeaderNames.CONTENT_TYPE) returns Some("application/xrds+xml") thenReturns Some("text/plain") ws.response.xml returns scala.xml.XML.loadString(readFixture("discovery/xrds/simple-op.xml")) ws.response.body returns "is_valid:false\n" val openId = new OpenIDClient(ws) Await.result(openId.verifiedId(setupMockRequest()), dur) must throwA[AUTH_ERROR.type] there was one(ws.request).post(any[Params])(any[Writeable[Params]], any[ContentTypeOf[Params]]) } "fail response verification if the response indicates an error" in { val ws = new WSMock ws.response.status returns OK thenReturns OK ws.response.header(HeaderNames.CONTENT_TYPE) returns Some("application/xrds+xml") thenReturns Some("text/plain") ws.response.xml returns scala.xml.XML.loadString(readFixture("discovery/xrds/simple-op.xml")) ws.response.body returns "is_valid:false\n" val openId = new OpenIDClient(ws) val errorResponse = (openIdResponse - "openid.mode") + ("openid.mode" -> Seq("error")) Await.result(openId.verifiedId(setupMockRequest(errorResponse)), dur) must throwA[BAD_RESPONSE.type] } // OpenID 1.1 compatibility - 14.2.1 "verify an OpenID 1.1 response that is missing the \"openid.op_endpoint\" parameter" in { val ws = createMockWithValidOpDiscoveryAndVerification val openId = new OpenIDClient(ws) val responseQueryString = (openIdResponse - "openid.op_endpoint") val userInfo = Await.result(openId.verifiedId(setupMockRequest(responseQueryString)), dur) "the claimedId must be present" in { userInfo.id must be equalTo claimedId } "using discovery and direct verification" in { got { // Use discovery to resolve the endpoint one(ws.request).get() // Verify the response one(ws.request).post(any[Params])(any[Writeable[Params]], any[ContentTypeOf[Params]]) } } } } def createMockWithValidOpDiscoveryAndVerification = { val ws = new WSMock ws.response.status returns OK thenReturns OK ws.response.header(HeaderNames.CONTENT_TYPE) returns Some("application/xrds+xml") thenReturns Some("text/plain") ws.response.xml returns scala.xml.XML.loadString(readFixture("discovery/xrds/simple-op.xml")) ws.response.body returns "is_valid:true\n" // http://openid.net/specs/openid-authentication-2_0.html#kvform ws } def setupMockRequest(queryString:Params = openIdResponse) = { val request = mock[Request[_]] request.queryString returns queryString request } def openIdResponse = createDefaultResponse(claimedId, identity, defaultSigned) } Other Play Framework source code examplesHere is a short list of links related to this Play Framework OpenIDSpec.scala source code file: |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.