curl --request POST \
--url https://{host}/api/auth/google/one-tap \
--header 'Content-Type: application/json' \
--data '
{
"credential": "<string>",
"device": "<string>"
}
'import requests
url = "https://{host}/api/auth/google/one-tap"
payload = {
"credential": "<string>",
"device": "<string>"
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({credential: '<string>', device: '<string>'})
};
fetch('https://{host}/api/auth/google/one-tap', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://{host}/api/auth/google/one-tap",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'credential' => '<string>',
'device' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://{host}/api/auth/google/one-tap"
payload := strings.NewReader("{\n \"credential\": \"<string>\",\n \"device\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://{host}/api/auth/google/one-tap")
.header("Content-Type", "application/json")
.body("{\n \"credential\": \"<string>\",\n \"device\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://{host}/api/auth/google/one-tap")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"credential\": \"<string>\",\n \"device\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"token": "<string>",
"user": {
"username": "<string>",
"role": "<string>",
"id": 123,
"email": "<string>",
"avatar": "<string>",
"display_name": "<string>",
"auth_source": "<string>",
"disabled": true,
"locale": "",
"landing_area": ""
}
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>",
"input": "<unknown>",
"ctx": {}
}
]
}Google One Tap
Sign in from a Google One Tap credential.
The only path here where the browser supplies the token rather than the
server fetching it, so everything hangs on the signature and audience check
in verify_google_id_token. Rate limited like the password route: an
unauthenticated POST that reaches Google’s key set is worth a ceiling even
though a forged credential cannot pass it.
One Tap is refused unless the prompt is switched on — otherwise turning off the button on the login page would leave the endpoint behind it open.
curl --request POST \
--url https://{host}/api/auth/google/one-tap \
--header 'Content-Type: application/json' \
--data '
{
"credential": "<string>",
"device": "<string>"
}
'import requests
url = "https://{host}/api/auth/google/one-tap"
payload = {
"credential": "<string>",
"device": "<string>"
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({credential: '<string>', device: '<string>'})
};
fetch('https://{host}/api/auth/google/one-tap', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://{host}/api/auth/google/one-tap",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'credential' => '<string>',
'device' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://{host}/api/auth/google/one-tap"
payload := strings.NewReader("{\n \"credential\": \"<string>\",\n \"device\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://{host}/api/auth/google/one-tap")
.header("Content-Type", "application/json")
.body("{\n \"credential\": \"<string>\",\n \"device\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://{host}/api/auth/google/one-tap")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"credential\": \"<string>\",\n \"device\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"token": "<string>",
"user": {
"username": "<string>",
"role": "<string>",
"id": 123,
"email": "<string>",
"avatar": "<string>",
"display_name": "<string>",
"auth_source": "<string>",
"disabled": true,
"locale": "",
"landing_area": ""
}
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>",
"input": "<unknown>",
"ctx": {}
}
]
}Response
Successful Response
A password or One Tap sign-in: the access token, and who it belongs to.
The refresh token is never here -- it travels only in the httpOnly cookie.
user is the account row in every mode but --no-auth, where it is the two
claims the local identity carries; the routes answer with
response_model_exclude_unset so that short form is not padded with nulls.