Skip to content

Commit 0ea65aa

Browse files
committed
modify optional clientSecret #36
1 parent 8cc4fe8 commit 0ea65aa

File tree

11 files changed

+45
-45
lines changed

11 files changed

+45
-45
lines changed

scala-oauth2-core/src/main/scala/scalaoauth2/provider/ClientCredentialFetcher.scala

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package scalaoauth2.provider
22

33
import org.apache.commons.codec.binary.Base64
44

5-
case class ClientCredential(clientId: String, clientSecret: String)
5+
case class ClientCredential(clientId: String, clientSecret: Option[String])
66

77
trait ClientCredentialFetcher {
88

@@ -17,15 +17,14 @@ trait ClientCredentialFetcher {
1717
val decoded = new String(Base64.decodeBase64(authorization.getBytes), "UTF-8")
1818
if (decoded.indexOf(':') > 0) {
1919
decoded.split(":", 2) match {
20-
case Array(clientId, clientSecret) => Some(ClientCredential(clientId, clientSecret))
21-
case Array(clientId) => Some(ClientCredential(clientId, ""))
22-
case _ => None
20+
case Array(clientId, clientSecret) => Some(ClientCredential(clientId, if (clientSecret == "") None else Some(clientSecret)))
21+
case Array(clientId) => Some(ClientCredential(clientId, None))
2322
}
2423
} else {
2524
None
2625
}
2726
case _ => request.clientId.map { clientId =>
28-
ClientCredential(clientId, request.clientSecret.getOrElse(""))
27+
ClientCredential(clientId, request.clientSecret)
2928
}
3029
}
3130
}

scala-oauth2-core/src/main/scala/scalaoauth2/provider/DataHandler.scala

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@ package scalaoauth2.provider
33
import java.util.Date
44
import scala.concurrent.Future
55

6-
case class AccessTokenRequest[U](clientId: String, clientSecret: String, user: U)
7-
86
/**
97
* Access token
108
*
@@ -33,7 +31,7 @@ case class AuthInfo[+U](user: U, clientId: Option[String], scope: Option[String]
3331
*
3432
* <h4>Authorization Code Grant</h4>
3533
* <ul>
36-
* <li>validateClient(clientId, clientSecret, grantType)</li>
34+
* <li>validateClient(clientCredential, grantType)</li>
3735
* <li>findAuthInfoByCode(code)</li>
3836
* <li>getStoredAccessToken(authInfo)</li>
3937
* <li>isAccessTokenExpired(token)</li>
@@ -43,14 +41,14 @@ case class AuthInfo[+U](user: U, clientId: Option[String], scope: Option[String]
4341
*
4442
* <h4>Refresh Token Grant</h4>
4543
* <ul>
46-
* <li>validateClient(clientId, clientSecret, grantType)</li>
44+
* <li>validateClient(clientCredential, grantType)</li>
4745
* <li>findAuthInfoByRefreshToken(refreshToken)</li>
4846
* <li>refreshAccessToken(authInfo, refreshToken)</li>
4947
* </ul>
5048
*
5149
* <h4>Resource Owner Password Credentials Grant</h4>
5250
* <ul>
53-
* <li>validateClient(clientId, clientSecret, grantType)</li>
51+
* <li>validateClient(clientCredential, grantType)</li>
5452
* <li>findUser(username, password)</li>
5553
* <li>getStoredAccessToken(authInfo)</li>
5654
* <li>isAccessTokenExpired(token)</li>
@@ -60,8 +58,8 @@ case class AuthInfo[+U](user: U, clientId: Option[String], scope: Option[String]
6058
*
6159
* <h4>Client Credentials Grant</h4>
6260
* <ul>
63-
* <li>validateClient(clientId, clientSecret, grantType)</li>
64-
* <li>findClientUser(clientId, clientSecret)</li>
61+
* <li>validateClient(clientCredential, grantType)</li>
62+
* <li>findClientUser(clientCredential)</li>
6563
* <li>getStoredAccessToken(authInfo)</li>
6664
* <li>isAccessTokenExpired(token)</li>
6765
* <li>refreshAccessToken(authInfo, token)
@@ -80,19 +78,18 @@ trait DataHandler[U] {
8078
/**
8179
* Verify proper client with parameters for issue an access token.
8280
*
83-
* @param clientId Client send this value which is registered by application.
84-
* @param clientSecret Client send this value which is registered by application.
85-
* @param grantType Client send this value which is registered by application.
81+
* @param clientCredential Client sends clientId and clientSecret which are registered by application.
82+
* @param grantType Client sends this value which is registered by application.
8683
* @return true if request is a regular client, false if request is a illegal client.
8784
*/
88-
def validateClient(clientId: String, clientSecret: String, grantType: String): Future[Boolean]
85+
def validateClient(clientCredential: ClientCredential, grantType: String): Future[Boolean]
8986

9087
/**
9188
* Find userId with username and password these are used on your system.
9289
* If you don't support Resource Owner Password Credentials Grant then doesn't need implementing.
9390
*
94-
* @param username Client send this value which is used on your system.
95-
* @param password Client send this value which is used on your system.
91+
* @param username Client sends this value which is used on your system.
92+
* @param password Client sends this value which is used on your system.
9693
* @return Including UserId to Option if could find the user, None if couldn't find.
9794
*/
9895
def findUser(username: String, password: String): Future[Option[U]]
@@ -128,7 +125,7 @@ trait DataHandler[U] {
128125
*
129126
* If you don't support Authorization Code Grant then doesn't need implementing.
130127
*
131-
* @param code Client send authorization code which is registered by system.
128+
* @param code Client sends authorization code which is registered by system.
132129
* @return Return authorized information that matched the code.
133130
*/
134131
def findAuthInfoByCode(code: String): Future[Option[AuthInfo[U]]]
@@ -138,7 +135,7 @@ trait DataHandler[U] {
138135
*
139136
* If you don't support Refresh Token Grant then doesn't need implementing.
140137
*
141-
* @param refreshToken Client send refresh token which is created by system.
138+
* @param refreshToken Client sends refresh token which is created by system.
142139
* @return Return authorized information that matched the refresh token.
143140
*/
144141
def findAuthInfoByRefreshToken(refreshToken: String): Future[Option[AuthInfo[U]]]
@@ -148,16 +145,15 @@ trait DataHandler[U] {
148145
*
149146
* If you don't support Client Credentials Grant then doesn't need implementing.
150147
*
151-
* @param clientId Client send this value which is registered by application.
152-
* @param clientSecret Client send this value which is registered by application.
148+
* @param clientCredential Client sends clientId and clientSecret which are registered by application.
153149
* @return Return user that matched both values.
154150
*/
155-
def findClientUser(clientId: String, clientSecret: String, scope: Option[String]): Future[Option[U]]
151+
def findClientUser(clientCredential: ClientCredential, scope: Option[String]): Future[Option[U]]
156152

157153
/**
158154
* Find AccessToken object by access token code.
159155
*
160-
* @param token Client send access token which is created by system.
156+
* @param token Client sends access token which is created by system.
161157
* @return Return access token that matched the token.
162158
*/
163159
def findAccessToken(token: String): Future[Option[AccessToken]]

scala-oauth2-core/src/main/scala/scalaoauth2/provider/GrantHandler.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ class ClientCredentials extends GrantHandler {
9595
val clientCredential = optionalClientCredential.getOrElse(throw new InvalidRequest("Client credential is required"))
9696
val scope = request.scope
9797

98-
dataHandler.findClientUser(clientCredential.clientId, clientCredential.clientSecret, scope).flatMap { optionalUser =>
98+
dataHandler.findClientUser(clientCredential, scope).flatMap { optionalUser =>
9999
val user = optionalUser.getOrElse(throw new InvalidGrant("client_id or client_secret or scope is incorrect"))
100100
val authInfo = AuthInfo(user, Some(clientCredential.clientId), scope, None)
101101

scala-oauth2-core/src/main/scala/scalaoauth2/provider/TokenEndpoint.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ trait TokenEndpoint {
1818
val handler = handlers.get(grantType).getOrElse(throw new UnsupportedGrantType("The grant_type is not supported"))
1919

2020
fetcher.fetch(request).map { clientCredential =>
21-
dataHandler.validateClient(clientCredential.clientId, clientCredential.clientSecret, grantType).flatMap { validClient =>
21+
dataHandler.validateClient(clientCredential, grantType).flatMap { validClient =>
2222
if (!validClient) {
2323
Future.successful(Left(throw new InvalidClient()))
2424
} else {

scala-oauth2-core/src/test/scala/scalaoauth2/provider/AuthorizationCodeSpec.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ class AuthorizationCodeSpec extends FlatSpec with ScalaFutures {
1111
it should "handle request" in {
1212
val authorizationCode = new AuthorizationCode()
1313
val request = AuthorizationRequest(Map(), Map("code" -> Seq("code1"), "redirect_uri" -> Seq("http://example.com/")))
14-
val f = authorizationCode.handleRequest(request, Some(ClientCredential("clientId1", "clientSecret1")), new MockDataHandler() {
14+
val f = authorizationCode.handleRequest(request, Some(ClientCredential("clientId1", Some("clientSecret1"))), new MockDataHandler() {
1515

1616
override def findAuthInfoByCode(code: String): Future[Option[AuthInfo[User]]] = Future.successful(Some(
1717
AuthInfo(user = MockUser(10000, "username"), clientId = Some("clientId1"), scope = Some("all"), redirectUri = Some("http://example.com/"))
@@ -32,7 +32,7 @@ class AuthorizationCodeSpec extends FlatSpec with ScalaFutures {
3232
it should "handle request if redirectUrl is none" in {
3333
val authorizationCode = new AuthorizationCode()
3434
val request = AuthorizationRequest(Map(), Map("code" -> Seq("code1"), "redirect_uri" -> Seq("http://example.com/")))
35-
val f = authorizationCode.handleRequest(request, Some(ClientCredential("clientId1", "clientSecret1")), new MockDataHandler() {
35+
val f = authorizationCode.handleRequest(request, Some(ClientCredential("clientId1", Some("clientSecret1"))), new MockDataHandler() {
3636

3737
override def findAuthInfoByCode(code: String): Future[Option[AuthInfo[MockUser]]] = Future.successful(Some(
3838
AuthInfo(user = MockUser(10000, "username"), clientId = Some("clientId1"), scope = Some("all"), redirectUri = None)

scala-oauth2-core/src/test/scala/scalaoauth2/provider/ClientCredentialFetcherSpec.scala

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,24 +9,29 @@ class ClientCredentialFetcherSpec extends FlatSpec {
99
val request = AuthorizationRequest(Map("Authorization" -> Seq("Basic Y2xpZW50X2lkX3ZhbHVlOmNsaWVudF9zZWNyZXRfdmFsdWU=")), Map())
1010
val Some(c) = ClientCredentialFetcher.fetch(request)
1111
c.clientId should be ("client_id_value")
12-
c.clientSecret should be ("client_secret_value")
12+
c.clientSecret should be (Some("client_secret_value"))
1313
}
1414

1515
it should "fetch Basic64 by case insensitive" in {
1616
val request = AuthorizationRequest(Map("authorization" -> Seq("Basic Y2xpZW50X2lkX3ZhbHVlOmNsaWVudF9zZWNyZXRfdmFsdWU=")), Map())
1717
val Some(c) = ClientCredentialFetcher.fetch(request)
1818
c.clientId should be ("client_id_value")
19-
c.clientSecret should be ("client_secret_value")
19+
c.clientSecret should be (Some("client_secret_value"))
2020
}
2121

22-
it should "fetch empty client_secret" in {
22+
it should "fetch authorization header without colon" in {
23+
val request = AuthorizationRequest(Map("Authorization" -> Seq("Basic Y2xpZW50X2lkX3ZhbHVl")), Map())
24+
ClientCredentialFetcher.fetch(request) should be (None)
25+
}
26+
27+
it should "fetch empty client_secret with colon" in {
2328
val request = AuthorizationRequest(Map("Authorization" -> Seq("Basic Y2xpZW50X2lkX3ZhbHVlOg==")), Map())
2429
val Some(c) = ClientCredentialFetcher.fetch(request)
2530
c.clientId should be ("client_id_value")
26-
c.clientSecret should be ("")
31+
c.clientSecret should be (None)
2732
}
2833

29-
it should "not fetch no Authorization key in header" in {
34+
it should "not fetch not Authorization key in header" in {
3035
val request = AuthorizationRequest(Map("authorizatio" -> Seq("Basic Y2xpZW50X2lkX3ZhbHVlOmNsaWVudF9zZWNyZXRfdmFsdWU=")), Map())
3136
ClientCredentialFetcher.fetch(request) should be (None)
3237
}
@@ -40,13 +45,13 @@ class ClientCredentialFetcherSpec extends FlatSpec {
4045
val request = AuthorizationRequest(Map(), Map("client_id" -> Seq("client_id_value"), "client_secret" -> Seq("client_secret_value")))
4146
val Some(c) = ClientCredentialFetcher.fetch(request)
4247
c.clientId should be ("client_id_value")
43-
c.clientSecret should be ("client_secret_value")
48+
c.clientSecret should be (Some("client_secret_value"))
4449
}
4550

4651
it should "omit client_secret" in {
4752
val Some(c) = ClientCredentialFetcher.fetch(AuthorizationRequest(Map(), Map("client_id" -> Seq("client_id_value"))))
4853
c.clientId should be ("client_id_value")
49-
c.clientSecret should be ("")
54+
c.clientSecret should be (None)
5055
}
5156

5257
it should "not fetch missing parameter" in {
@@ -65,6 +70,6 @@ class ClientCredentialFetcherSpec extends FlatSpec {
6570
)
6671
val Some(c) = ClientCredentialFetcher.fetch(request)
6772
c.clientId should be ("client_id_value")
68-
c.clientSecret should be ("client_secret_value")
73+
c.clientSecret should be (Some("client_secret_value"))
6974
}
7075
}

scala-oauth2-core/src/test/scala/scalaoauth2/provider/ClientCredentialsSpec.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ class ClientCredentialsSpec extends FlatSpec with ScalaFutures {
1111
it should "handle request" in {
1212
val clientCredentials = new ClientCredentials()
1313
val request = AuthorizationRequest(Map(), Map("scope" -> Seq("all")))
14-
val f = clientCredentials.handleRequest(request, Some(ClientCredential("clientId1", "clientSecret1")), new MockDataHandler() {
14+
val f = clientCredentials.handleRequest(request, Some(ClientCredential("clientId1", Some("clientSecret1"))), new MockDataHandler() {
1515

16-
override def findClientUser(clientId: String, clientSecret: String, scope: Option[String]): Future[Option[User]] = Future.successful(Some(MockUser(10000, "username")))
16+
override def findClientUser(clientCredential: ClientCredential, scope: Option[String]): Future[Option[User]] = Future.successful(Some(MockUser(10000, "username")))
1717

1818
override def createAccessToken(authInfo: AuthInfo[User]): Future[AccessToken] = Future.successful(AccessToken("token1", None, Some("all"), Some(3600), new java.util.Date()))
1919
})

scala-oauth2-core/src/test/scala/scalaoauth2/provider/MockDataHandler.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ case class MockUser(id: Long, name: String) extends User
88

99
class MockDataHandler extends DataHandler[User] {
1010

11-
def validateClient(clientId: String, clientSecret: String, grantType: String): Future[Boolean] = Future.successful(false)
11+
def validateClient(clientCredential: ClientCredential, grantType: String): Future[Boolean] = Future.successful(false)
1212

1313
def findUser(username: String, password: String): Future[Option[User]] = Future.successful(None)
1414

@@ -18,7 +18,7 @@ class MockDataHandler extends DataHandler[User] {
1818

1919
def findAuthInfoByRefreshToken(refreshToken: String): Future[Option[AuthInfo[User]]] = Future.successful(None)
2020

21-
def findClientUser(clientId: String, clientSecret: String, scope: Option[String]): Future[Option[User]] = Future.successful(None)
21+
def findClientUser(clientCredential: ClientCredential, scope: Option[String]): Future[Option[User]] = Future.successful(None)
2222

2323
def findAccessToken(token: String): Future[Option[AccessToken]] = Future.successful(None)
2424

scala-oauth2-core/src/test/scala/scalaoauth2/provider/PasswordSpec.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ class PasswordSpec extends FlatSpec with ScalaFutures {
1313
override def clientCredentialRequired = false
1414
}
1515

16-
"Password when client credential required" should "handle request" in handlesRequest(passwordClientCredReq, Some(ClientCredential("clientId1", "clientSecret1")))
16+
"Password when client credential required" should "handle request" in handlesRequest(passwordClientCredReq, Some(ClientCredential("clientId1", Some("clientSecret1"))))
1717
"Password when client credential not required" should "handle request" in handlesRequest(passwordNoClientCredReq, None)
1818

1919
def handlesRequest(password: Password, clientCredential: Option[ClientCredential]) = {

scala-oauth2-core/src/test/scala/scalaoauth2/provider/RefreshTokenSpec.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ class RefreshTokenSpec extends FlatSpec with ScalaFutures {
1111
it should "handle request" in {
1212
val refreshToken = new RefreshToken()
1313
val request = AuthorizationRequest(Map(), Map("refresh_token" -> Seq("refreshToken1")))
14-
val f = refreshToken.handleRequest(request, Some(ClientCredential("clientId1", "clientSecret1")), new MockDataHandler() {
14+
val f = refreshToken.handleRequest(request, Some(ClientCredential("clientId1", Some("clientSecret1"))), new MockDataHandler() {
1515

1616
override def findAuthInfoByRefreshToken(refreshToken: String): Future[Option[AuthInfo[User]]] =
1717
Future.successful(Some(AuthInfo(user = MockUser(10000, "username"), clientId = Some("clientId1"), scope = None, redirectUri = None)))

0 commit comments

Comments
 (0)