add bc for basic auth in legacy oauth flow
parent
5a1b3b0661
commit
0c66ed94d5
|
@ -97,7 +97,7 @@ final class OAuth(env: Env) extends LilaController(env) {
|
||||||
|
|
||||||
def legacyTokenApply =
|
def legacyTokenApply =
|
||||||
Action.async(parse.form(accessTokenRequestForm)) { implicit req =>
|
Action.async(parse.form(accessTokenRequestForm)) { implicit req =>
|
||||||
req.body.prepareLegacy match {
|
req.body.prepareLegacy(AccessTokenRequest.BasicAuth from req) match {
|
||||||
case Validated.Valid(prepared) =>
|
case Validated.Valid(prepared) =>
|
||||||
env.oAuth.authorizationApi.consume(prepared) flatMap {
|
env.oAuth.authorizationApi.consume(prepared) flatMap {
|
||||||
case Validated.Valid(granted) =>
|
case Validated.Valid(granted) =>
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
package lila.oauth
|
package lila.oauth
|
||||||
|
|
||||||
import cats.data.Validated
|
import cats.data.Validated
|
||||||
|
|
||||||
|
import play.api.http.HeaderNames
|
||||||
|
import play.api.mvc.RequestHeader
|
||||||
|
|
||||||
|
import lila.common.String.base64
|
||||||
import lila.user.User
|
import lila.user.User
|
||||||
|
|
||||||
object AccessTokenRequest {
|
object AccessTokenRequest {
|
||||||
|
@ -23,24 +28,27 @@ object AccessTokenRequest {
|
||||||
.andThen(Protocol.CodeVerifier.from)
|
.andThen(Protocol.CodeVerifier.from)
|
||||||
clientId <- clientId.map(ClientId.apply).toValid(Error.ClientIdRequired)
|
clientId <- clientId.map(ClientId.apply).toValid(Error.ClientIdRequired)
|
||||||
redirectUri <- redirectUri.map(UncheckedRedirectUri.apply).toValid(Error.RedirectUriRequired)
|
redirectUri <- redirectUri.map(UncheckedRedirectUri.apply).toValid(Error.RedirectUriRequired)
|
||||||
} yield Prepared(grantType, code, codeVerifier.some, clientId.some, redirectUri.some, None)
|
} yield Prepared(grantType, code, codeVerifier.some, clientId, redirectUri, None)
|
||||||
|
|
||||||
def prepareLegacy: Validated[Error, Prepared] =
|
def prepareLegacy(auth: Option[BasicAuth]): Validated[Error, Prepared] =
|
||||||
for {
|
for {
|
||||||
grantType <- grantType.toValid(Error.GrantTypeRequired).andThen(GrantType.from)
|
grantType <- grantType.toValid(Error.GrantTypeRequired).andThen(GrantType.from)
|
||||||
code <- code.map(AuthorizationCode.apply).toValid(Error.CodeRequired)
|
code <- code.map(AuthorizationCode.apply).toValid(Error.CodeRequired)
|
||||||
|
clientId <- clientId.map(ClientId.apply).orElse(auth.map(_.clientId)).toValid(Error.ClientIdRequired)
|
||||||
clientSecret <- clientSecret
|
clientSecret <- clientSecret
|
||||||
.map(LegacyClientApi.ClientSecret)
|
.map(LegacyClientApi.ClientSecret)
|
||||||
|
.orElse(auth.map(_.clientSecret))
|
||||||
.toValid(LegacyClientApi.ClientSecretRequired)
|
.toValid(LegacyClientApi.ClientSecretRequired)
|
||||||
} yield Prepared(grantType, code, None, clientId.map(ClientId.apply), None, clientSecret.some)
|
redirectUri <- redirectUri.map(UncheckedRedirectUri.apply).toValid(Error.RedirectUriRequired)
|
||||||
|
} yield Prepared(grantType, code, None, clientId, redirectUri, clientSecret.some)
|
||||||
}
|
}
|
||||||
|
|
||||||
case class Prepared(
|
case class Prepared(
|
||||||
grantType: GrantType,
|
grantType: GrantType,
|
||||||
code: AuthorizationCode,
|
code: AuthorizationCode,
|
||||||
codeVerifier: Option[CodeVerifier],
|
codeVerifier: Option[CodeVerifier],
|
||||||
clientId: Option[ClientId],
|
clientId: ClientId,
|
||||||
redirectUri: Option[UncheckedRedirectUri],
|
redirectUri: UncheckedRedirectUri,
|
||||||
clientSecret: Option[LegacyClientApi.ClientSecret]
|
clientSecret: Option[LegacyClientApi.ClientSecret]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -49,4 +57,19 @@ object AccessTokenRequest {
|
||||||
scopes: List[OAuthScope],
|
scopes: List[OAuthScope],
|
||||||
redirectUri: RedirectUri
|
redirectUri: RedirectUri
|
||||||
)
|
)
|
||||||
|
|
||||||
|
case class BasicAuth(clientId: ClientId, clientSecret: LegacyClientApi.ClientSecret)
|
||||||
|
object BasicAuth {
|
||||||
|
def from(req: RequestHeader): Option[BasicAuth] =
|
||||||
|
req.headers.get(HeaderNames.AUTHORIZATION).flatMap { authorization =>
|
||||||
|
val prefix = "Basic "
|
||||||
|
authorization.startsWith(prefix) option authorization.stripPrefix(prefix)
|
||||||
|
} flatMap base64.decode flatMap {
|
||||||
|
_.split(":", 2) match {
|
||||||
|
case Array(clientId, clientSecret) =>
|
||||||
|
Some(BasicAuth(ClientId(clientId), LegacyClientApi.ClientSecret(clientSecret)))
|
||||||
|
case _ => None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,10 +33,8 @@ final class AuthorizationApi(val coll: Coll)(implicit ec: scala.concurrent.Execu
|
||||||
.result[PendingAuthorization]
|
.result[PendingAuthorization]
|
||||||
.toValid(Protocol.Error.AuthorizationCodeInvalid)
|
.toValid(Protocol.Error.AuthorizationCodeInvalid)
|
||||||
.ensure(Protocol.Error.AuthorizationCodeExpired)(_.expires.isAfter(DateTime.now()))
|
.ensure(Protocol.Error.AuthorizationCodeExpired)(_.expires.isAfter(DateTime.now()))
|
||||||
.ensure(Protocol.Error.MismatchingRedirectUri)(p =>
|
.ensure(Protocol.Error.MismatchingRedirectUri)(_.redirectUri.matches(request.redirectUri))
|
||||||
request.redirectUri.forall(p.redirectUri.matches)
|
.ensure(Protocol.Error.MismatchingClient)(_.clientId == request.clientId)
|
||||||
)
|
|
||||||
.ensure(Protocol.Error.MismatchingClient)(p => request.clientId.forall(_ == p.clientId))
|
|
||||||
_ <- pending.challenge match {
|
_ <- pending.challenge match {
|
||||||
case Left(hashedClientSecret) =>
|
case Left(hashedClientSecret) =>
|
||||||
request.clientSecret
|
request.clientSecret
|
||||||
|
|
Loading…
Reference in New Issue