Invalid Grant Malformed Auth Code

  1. Versions: Nakama {3.20.0}, {Docker}, {Godot 3.5.3}
  2. Server Framework Runtime language (If relevant) {Go, Lua}

Hello, I’m having some issues with the Google Auth. Not sure if I’m just not as good at searching as I used to be or what but can’t seem to find much on this particular case. Everything in auth is succeeding until I pass it to Nakama to authenticate.

Relevant Errors

dev-nakama-1       | {"level":"debug","ts":"2024-07-03T06:21:45.663Z","caller":"social/social.go:349","msg":"Checking Google ID","idToken":"ya29.a0AXooCgvHQIWef4P2WP88ecVeBdEIb923SzX48w6S6qW9kCa0XvaPuooe8Vn5meSuvLlYY7gWu6-jRjQb4c8GM4PVis1y7PA5sJ4aid7vBbVg81SHlIqDKLza5CtalUYwTjHuR_xPPSX6Eh1kS-1WELDJWb6esPsuXIFEaCgYKAZYSARISFQHGX2Mi3Qvf1Rhtt0LrtK2yhj0F1w0171"}
dev-nakama-1       | {"level":"debug","ts":"2024-07-03T06:21:46.060Z","caller":"social/social.go:340","msg":"Failed to exchange authorization code for a token.","error":"oauth2: \"invalid_grant\" \"Malformed auth code.\""}
dev-nakama-1       | {"level":"debug","ts":"2024-07-03T06:21:46.061Z","caller":"social/social.go:432","msg":"Failed to exchange an authorization code for an access token.","auth_token":"ya29.a0AXooCgvHQIWef4P2WP88ecVeBdEIb923SzX48w6S6qW9kCa0XvaPuooe8Vn5meSuvLlYY7gWu6-jRjQb4c8GM4PVis1y7PA5sJ4aid7vBbVg81SHlIqDKLza5CtalUYwTjHuR_xPPSX6Eh1kS-1WELDJWb6esPsuXIFEaCgYKAZYSARISFQHGX2Mi3Qvf1Rhtt0LrtK2yhj0F1w0171","error":"failed to exchange authorization code for a token"}
dev-nakama-1       | {"level":"info","ts":"2024-07-03T06:21:46.061Z","caller":"server/core_authenticate.go:632","msg":"Could not authenticate Google profile.","error":"google id token invalid"}

Google Auth Flow

func authorize():
	if !yield(is_token_valid(), "completed"):
		if !yield(refresh_tokens(), "completed"):
			get_auth_code()

func is_token_valid():
	if !token:
		yield(Engine.get_main_loop(), "idle_frame")
		return false
	
	var headers = PoolStringArray(Standard_Headers)
	var body = "access_token=%s" % token

	var response = handle_request(headers, body, token_req + "info")
	var expiration = parse_json(response[3].get_string_from_utf8()).get("expires_in")
	if expiration and int(expiration) > 0:
		print("Token is valid")
		emit_signal("token_received", token)
		return true
	else:
		return false

func handle_request(headers, body, uri) -> void:
	var http_request = HTTPRequest.new()
	
	add_child(http_request)
	
	var ERR = http_request.request(uri, headers, true, HTTPClient.METHOD_POST, body)
	if ERR != OK:
		push_error("An error occurred in the HTTP request with ERR code: %s" % ERR)
		
	var response = yield(http_request, "request_completed")
	return response

func get_auth_code() -> void:
	set_process(true)
	
	var redir_err = redirect_server.listen(PORT, BIND)
	
	var body_parts = [
		"client_id=%s" % client_ID,
		"redirect_uri=%s" % redirect_uri,
		"response_type=code",
		"scope=https://www.googleapis.com/auth/games",
	]
	
	var url = auth_serve + "?" + PoolStringArray(body_parts).join("&")
	
	OS.shell_open(url)

func get_token_from_auth(auth_code):
	var headers = PoolStringArray(Standard_Headers)
	
	var body_parts = [
		"code=%s" % auth_code.http_unescape(),
		"client_id=%s" % client_ID,
		"client_secret=%s" % client_secret,
		"redirect_uri=%s" % redirect_uri,
		"grant_type=authorization_code",
	]
	
	var body = PoolStringArray(body_parts).join("&")
	
	var response = yield(handle_request(headers, body, token_req), "completed")
	var response_body = parse_json(response[3].get_string_from_utf8())
	token = response_body["access_token"]
	#refresh_token = response_body["refresh_token"]
	emit_signal("token_received", token)

If any additional info is needed please let me know.

Thanks