Group Group Group Group Group Group Group Group Group

Ch 22 Google Auth - {"error":true,"reason":"Value required for key 'access_token'."}

I am getting the following error at the final Run in the chapter.

{"error":true,"reason":"Value required for key 'access_token'."}

I tried everything I could think of in my own code. Then I loaded up the starter project for chapter 23, and got the same results…

Not sure what else to try on this one? I did a swift package update and then a vapor build. Using latest greatest public Xcode version.

@viper827 what request/point in the login with Google flow are you getting that error? I’ve just tried with and it works

So it lets me click the button, I get taken to the google page to pick the account I wish to use, and then once it redirects me back to my page I get the error.

Can you show your ImperialController.swift? It’s like something is out of whack, especially as I can’t reproduce it :thinking:

import Vapor
import Imperial
import Authentication

struct ImperialController: RouteCollection {
  func boot(router: Router) throws {
guard let googleCallbackURL = Environment.get("GOOGLE_CALLBACK_URL") else {
  fatalError("Callback URL not set")
try router.oAuth(from: Google.self, authenticate: "login-google", callback: googleCallbackURL,
                 scope: ["profile", "email"], completion: processGoogleLogin)

func processGoogleLogin(request: Request, token: String) throws -> Future<ResponseEncodable> {
return try Google.getUser(on: request).flatMap(to: ResponseEncodable.self) { userInfo in
  return User.query(on: request).filter(\.username ==
             .first().flatMap(to: ResponseEncodable.self) { foundUser in
    guard let existingUser = foundUser else {
      let user = User(name:, username:, password: UUID().uuidString)
      return request).map(to: ResponseEncodable.self) { user in
        try request.authenticateSession(user)
        return request.redirect(to: "/")
    try request.authenticateSession(existingUser)
    return request.future(request.redirect(to: "/"))

struct GoogleUserInfo: Content {
let email: String
let name: String

extension Google {
static func getUser(on request: Request) throws -> Future<GoogleUserInfo> {
var headers = HTTPHeaders()
headers.bearerAuthorization = try BearerAuthorization(token: request.accessToken())

let googleAPIURL = ""
return try request.client().get(googleAPIURL, headers: headers).map(to: GoogleUserInfo.self) { response in
  guard response.http.status == .ok else {
    if response.http.status == .unauthorized {
      throw Abort.redirect(to: "/login-google")
    } else {
      throw Abort(.internalServerError)
  return try response.content.syncDecode(GoogleUserInfo.self)

I’m using the completed file that provided with the book.

@viper827 if you breakpoint I’m assuming it’s not hitting your code and is failing inside Imeperial? Does it work if you try with the whole Vapor TIL project from GH?

@viper827 Do you still have issues with this?