title: OAuth with KeyCloak in Ktor : Is it supposed to work like this?
body: <p>I tried to set up a working Oauth2 authorization via Keycloak in a Ktor web server. The expected flow would be sending a request from the web server to keycloak and logging in on the given UI, then Keycloak sends back a code that can be used to receive a token. Like <a href="https://www.appsdeveloperblog.com/keycloak-authorization-code-grant-example/" rel="noreferrer">here</a></p>
  <p>First I did it based on the examples in Ktor's documentation. <a href="https://ktor.io/docs/oauth.html#example" rel="noreferrer">Oauth</a> It worked fine until it got to the point where I had to receive the token, then it just gave me HTTP status 401. Even though the curl command works properly. Then I tried an example project I found on <a href="https://github.com/imalik8088/ktor-starter" rel="noreferrer">GitHub</a> , I managed to make it work by building my own HTTP request and sending it to the Keycloak server to receive the token, but is it supposed to work like this?</p>
  <p>I have multiple questions regarding this.</p>
  <ol>
  <li><p>Is this function supposed to handle both authorization and getting the token?</p>
  <pre><code> authenticate(keycloakOAuth) {
       get(&quot;/oauth&quot;) {
           val principal = call.authentication.principal&lt;OAuthAccessTokenResponse.OAuth2&gt;()
  
           call.respondText(&quot;Access Token = ${principal?.accessToken}&quot;)
       }
   }
  </code></pre>
  </li>
  <li><p>I think my configuration is correct, since I can receive the authorization, just not the token.</p>
  <pre><code>const val KEYCLOAK_ADDRESS = &quot;**&quot;
  
  val keycloakProvider = OAuthServerSettings.OAuth2ServerSettings(
  name = &quot;keycloak&quot;,
  authorizeUrl = &quot;$KEYCLOAK_ADDRESS/auth/realms/production/protocol/openid-connect/auth&quot;,
  accessTokenUrl = &quot;$KEYCLOAK_ADDRESS/auth/realms/production/protocol/openid-connect/token&quot;,
  clientId = &quot;**&quot;,
  clientSecret = &quot;**&quot;,
  accessTokenRequiresBasicAuth = false,
  requestMethod = HttpMethod.Post, // must POST to token endpoint
  defaultScopes = listOf(&quot;roles&quot;)
  )
  const val keycloakOAuth = &quot;keycloakOAuth&quot;
  
   install(Authentication) {
       oauth(keycloakOAuth) {
       client = HttpClient(Apache)
       providerLookup = { keycloakProvider }
       urlProvider = { &quot;http://localhost:8080/token&quot; }
   }
  }
  </code></pre>
  </li>
  <li><p>There is this /token route I made with a built HTTP request, this one manages to get the token, but it feels like a hack.</p>
  <pre><code>get(&quot;/token&quot;){
   var grantType = &quot;authorization_code&quot;
   val code = call.request.queryParameters[&quot;code&quot;]
   val requestBody = &quot;grant_type=${grantType}&amp;&quot; +
           &quot;client_id=${keycloakProvider.clientId}&amp;&quot; +
           &quot;client_secret=${keycloakProvider.clientSecret}&amp;&quot; +
           &quot;code=${code.toString()}&amp;&quot; +
           &quot;redirect_uri=http://localhost:8080/token&quot;
  
   val tokenResponse = httpClient.post&lt;HttpResponse&gt;(keycloakProvider.accessTokenUrl) {
       headers {
           append(&quot;Content-Type&quot;,&quot;application/x-www-form-urlencoded&quot;)
       }
       body = requestBody
   }
   call.respondText(&quot;Access Token = ${tokenResponse.readText()}&quot;)
  }
  </code></pre>
  </li>
  </ol>
  <p>TL;DR: I can log in via Keycloak fine, but trying to get an access_token gives me 401. Is the authenticate function in ktor supposed to handle that too?</p>