add bc for basic auth in legacy oauth flow

pull/9350/head
Niklas Fiekas 2021-07-05 11:29:22 +02:00
parent 5a1b3b0661
commit 0c66ed94d5
3 changed files with 31 additions and 10 deletions

View File

@ -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) =>

View File

@ -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
}
}
}
} }

View File

@ -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