Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementing stateless OAuth #440

Open
vojkny opened this issue Jun 9, 2020 · 2 comments
Open

Implementing stateless OAuth #440

vojkny opened this issue Jun 9, 2020 · 2 comments

Comments

@vojkny
Copy link
Contributor

vojkny commented Jun 9, 2020

I am going through the OAuth examples here:

But both of them propose implementation as a filter, meaning they protect certain resource. Both examples somehow store the fact that the user is logged (cookie/header) and let them visit the resource.

Instead of redirecting to the protected resource (in this case /), I would like to directly respond with custom JSON response immediately after the token callback. This response requires working with the authorization callback response, so it is too late to build it after the redirect back to the / where the authorization started.

Is this feasible with the oauth module?

@nlochschmidt
Copy link
Contributor

nlochschmidt commented Aug 20, 2020

I am assuming you are referring to a callback from an implicit grant or an authorization code grant. I had to do something similar in the past but it honestly felt really awkward.

What I did was implementing a custom OAuthPersistence similar to the InsecureCookieBasedOAuthPersistence. However instead of storing the access token, I overwrote the retrieveToken and assignToken methods similar to this:

override fun retrieveToken(request: Request): AccessToken? = request.header("Authorization")?.removePrefix("Bearer ")?.let(::AccessToken)

override fun assignToken(request: Request, redirect: Response, accessToken: AccessToken): Response {
  val internalAuthorizedRequest = Request(GET, Header.LOCATION(redirect)).header("Authorization", "Bearer ${accessToken.value}")
  return getApp()(internalAuthorizedRequest)
            .invalidateCookie(csrfName)
            .invalidateCookie(nonceName)
}

getApp is a function () -> HttpHandler passed into the OAuthPersistence that gives me the protected app with the authFilter in front. getApp has to be a function to deal with the fact that OAuthPersistence has to be created before the OAuthProvider is created:

    var authProvider: OAuthProvider? = null
    val protectedApp: HttpHandler by lazy { authProvider!!.authFilter.then(/** add your app here **/) })
    authProvider = OAuthProvider.gitHub(
        ..., 
        oAuthPersistence = StatelessOAuthPersistence( getApp = { protectedApp }
    )

    val appAndOAuthCallback: HttpHandler = routes(
            authProvider.callbackEndpoint,
            "/" bind GET to protectedApp,
            "/{:.*}" bind GET to protectedApp)
    appAndOAuthCallback.asServer(Jetty(8080)).start()

At least two problems with this solution:

  1. It currently only works with GET requests to the protected resource. Any POST body or custom headers would get lost due to the redirect anyways.
  2. I haven't found a way to get access to the idToken yet (only relevant with OpenID Connect)

There are probably lots of other issues with this approach 😉

@s4nchez
Copy link
Collaborator

s4nchez commented Aug 22, 2020

@knyttl do you want to return the resource as part of the authorization callback? Or the access token request?

Either way, I believe that goes against the standard which tries to decouple authorization server from the actual resource. But happy to consider if that's allowed by the standard (that's a new one for me).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants