Motyw
Ogłoszenia lokalne. Kupuj, wystawiaj, sprzedawaj, ogłaszaj.Ustaw kolor:Pakiety ogłoszeń Kup 1G Dołącz
PL
Zarejestruj sięRejestracja

Zaloguj przez 1g.pl

Wstaw na swojej stronie jeden przycisk — a Twoi użytkownicy zalogują się kontem z 1g.pl, bez zakładania u Ciebie kolejnego hasła. Dostajesz imię i nazwisko, adres e-mail i awatar. Działa dokładnie tak, jak przycisk Google: standard OAuth 2.0, kod autoryzacyjny z PKCE.

Zaloguj przez 1g.pl

Załóż aplikację i odbierz client_id

Cztery kroki:
  1. Zarejestruj aplikację — dostajesz client_id i sekret
  2. Wstaw przycisk — przenosi użytkownika do nas
  3. Wymień kod na token — po stronie swojego serwera
  4. Pobierz dane — imię, e-mail, awatar
1

Zarejestruj aplikację

Wejdź w Moje integracje i podaj nazwę oraz adres powrotu — stronę u siebie, na którą Cię odeślemy po zalogowaniu. W zamian dostajesz dwie rzeczy:

CoGdzie to trzymać
client_id
32 znaki
Jawny. Wpisujesz go w kod strony, widzi go każdy — i tak ma być.
client_secret
43 znaki
Wyłącznie na Twoim serwerze. Nigdy w kodzie strony, nigdy w aplikacji mobilnej, nigdy w repozytorium. Pokazujemy go raz — u nas leży tylko jego odcisk, więc drugi raz go nie odzyskasz.
Adres powrotu sprawdzamy co do znakuhttps://twoja.pl/odbior i https://twoja.pl/odbior/ to dla nas dwa różne adresy. Porównanie „zaczyna się od" pozwoliłoby komuś, kto zna Twój client_id, dopisać własną ścieżkę i przejąć kod logowania — dlatego go nie stosujemy. Wymagamy HTTPS; wyjątkiem jest localhost, żeby dało się pracować na własnym komputerze.
2

Wstaw przycisk

Najprostsza wersja to zwykły odnośnik. Podmień TWOJ_CLIENT_ID i adres powrotu na swoje:

HTML — przycisk
<a class="logowanie-1g"
   href="https://1g.pl/api/oauth/authorize.php
        ?client_id=TWOJ_CLIENT_ID
        &redirect_uri=https%3A%2F%2Ftwoja.pl%2Fodbior
        &response_type=code
        &scope=profil%20email
        &state=LOSOWY_CIAG_Z_SESJI">
  <img src="https://1g.pl/assets/img/logowanie-1g.svg" alt="" width="20" height="20">
  Zaloguj przez 1g.pl
</a>

Wygląd przycisku — do wklejenia w swój arkusz stylów:

CSS — wygląd przycisku
.logowanie-1g {
  display: inline-flex; align-items: center; gap: 9px;
  padding: 11px 20px; min-height: 44px;
  border: 1px solid #d0d5dd; border-radius: 9px;
  background: #fff; color: #1a202c;
  font: 600 15px/1 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  text-decoration: none;
}
.logowanie-1g:hover { background: #f7f9fc; }

Parametry adresu

ParametrWymaganyZnaczenie
client_idtakZ panelu „Moje integracje”.
redirect_uritakJeden z adresów powrotu podanych przy rejestracji, zakodowany (urlencode).
response_typetakZawsze code. Innego przepływu świadomie nie wystawiamy.
scopenieprofil (imię, nazwisko, awatar), email. Rozdzielone spacją. Domyślnie oba.
statezalecanyLosowy ciąg, który zapisujesz w sesji użytkownika. Oddamy go bez zmian — porównaj po powrocie.
code_challengezalecanyPKCE, patrz niżej.
code_challenge_methodz PKCES256 albo plain. Używaj S256.
Po co state Bez niego ktoś może podstawić Twojemu zalogowanemu użytkownikowi własny kod autoryzacyjny i połączyć jego konto u Ciebie ze swoim kontem w 1g.pl. Losowy ciąg w sesji i porównanie po powrocie zamykają tę drogę. To trzy linijki kodu.
3

Wymień kod na token

Wracamy na Twój adres powrotu z parametrami code i state. Kod żyje 60 sekund i działa raz. Wymieniasz go na token — i to musi się dziać na Twoim serwerze, bo dopiero tu pojawia się sekret.

PHP — komplet: przycisk, powrót, dane
<?php
session_start();

const CLIENT_ID     = 'TWOJ_CLIENT_ID';
const CLIENT_SECRET = 'TWOJ_SEKRET';          // tylko tutaj, nigdy w kodzie strony
const REDIRECT_URI  = 'https://twoja.pl/odbior.php';

/* ── Wyjście: przenosimy użytkownika do 1g.pl ─────────────────────────── */
if (!isset($_GET['code'])) {
    $_SESSION['1g_state']    = bin2hex(random_bytes(16));
    $_SESSION['1g_verifier'] = rtrim(strtr(base64_encode(random_bytes(32)), '+/', '-_'), '=');

    $wyzwanie = rtrim(strtr(base64_encode(
        hash('sha256', $_SESSION['1g_verifier'], true)), '+/', '-_'), '=');

    header('Location: https://1g.pl/api/oauth/authorize.php?' . http_build_query([
        'client_id'             => CLIENT_ID,
        'redirect_uri'          => REDIRECT_URI,
        'response_type'         => 'code',
        'scope'                 => 'profil email',
        'state'                 => $_SESSION['1g_state'],
        'code_challenge'        => $wyzwanie,
        'code_challenge_method' => 'S256',
    ]));
    exit;
}

/* ── Powrót: najpierw state, potem cokolwiek innego ───────────────────── */
if (!hash_equals($_SESSION['1g_state'] ?? '', $_GET['state'] ?? '')) {
    http_response_code(400);
    exit('Niezgodny state — to logowanie nie zaczęło się u nas.');
}

/* ── Kod → token (serwer–serwer) ──────────────────────────────────────── */
$ch = curl_init('https://1g.pl/api/oauth/token.php');
curl_setopt_array($ch, [
    CURLOPT_POST           => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT        => 15,
    CURLOPT_POSTFIELDS     => http_build_query([
        'grant_type'    => 'authorization_code',
        'code'          => $_GET['code'],
        'redirect_uri'  => REDIRECT_URI,      // ten sam co wyżej, co do znaku
        'client_id'     => CLIENT_ID,
        'client_secret' => CLIENT_SECRET,
        'code_verifier' => $_SESSION['1g_verifier'],
    ]),
]);
$odp = json_decode((string)curl_exec($ch), true);
curl_close($ch);

if (empty($odp['access_token'])) {
    http_response_code(400);
    exit('Logowanie nieudane: ' . ($odp['error_description'] ?? $odp['error'] ?? '?'));
}

/* ── Token → dane użytkownika ─────────────────────────────────────────── */
$ch = curl_init('https://1g.pl/api/oauth/userinfo.php');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT        => 15,
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $odp['access_token']],
]);
$user = json_decode((string)curl_exec($ch), true);
curl_close($ch);

/* $user['sub'] to stały numer konta w 1g.pl — po nim rozpoznajesz powracającego.
   Nie po e-mailu: e-mail wolno zmienić, numer nie. */
$_SESSION['moj_uzytkownik'] = $user;
header('Location: /');
Node.js — ta sama wymiana
import crypto from 'node:crypto';

const CLIENT_ID = 'TWOJ_CLIENT_ID';
const CLIENT_SECRET = process.env.CLIENT_SECRET_1G;   // ze zmiennej środowiskowej
const REDIRECT_URI = 'https://twoja.pl/odbior';

const b64url = (buf) => buf.toString('base64url');

// Wyjście
export function adresLogowania(sesja) {
  sesja.state = b64url(crypto.randomBytes(16));
  sesja.verifier = b64url(crypto.randomBytes(32));
  const wyzwanie = b64url(crypto.createHash('sha256').update(sesja.verifier).digest());

  const p = new URLSearchParams({
    client_id: CLIENT_ID,
    redirect_uri: REDIRECT_URI,
    response_type: 'code',
    scope: 'profil email',
    state: sesja.state,
    code_challenge: wyzwanie,
    code_challenge_method: 'S256',
  });
  return `https://1g.pl/api/oauth/authorize.php?${p}`;
}

// Powrót
export async function odbior(sesja, query) {
  if (query.state !== sesja.state) throw new Error('Niezgodny state');

  const odp = await fetch('https://1g.pl/api/oauth/token.php', {
    method: 'POST',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    body: new URLSearchParams({
      grant_type: 'authorization_code',
      code: query.code,
      redirect_uri: REDIRECT_URI,
      client_id: CLIENT_ID,
      client_secret: CLIENT_SECRET,
      code_verifier: sesja.verifier,
    }),
  }).then(r => r.json());

  if (!odp.access_token) throw new Error(odp.error_description || odp.error);

  return fetch('https://1g.pl/api/oauth/userinfo.php', {
    headers: { Authorization: `Bearer ${odp.access_token}` },
  }).then(r => r.json());
}

PKCE — po co ta dodatkowa para

Losujesz code_verifier, wysyłasz do nas jego skrót (code_challenge), a przy wymianie kodu pokazujesz oryginał. Kto przechwyci sam kod — z historii przeglądarki, z nagłówka odsyłającego, z dziennika pośrednika — nie wymieni go bez tej wartości, bo nigdy nie opuściła Twojego serwera. U nas PKCE jest nieobowiązkowe, ale kod przysłany z wyzwaniem wymaga weryfikatora przy wymianie — nie da się go po drodze pominąć.

4

Co dostajesz

Odpowiedź /userinfo
{
  "sub": "84213",
  "iss": "https://1g.pl",
  "name": "Anna Kowalska",
  "given_name": "Anna",
  "family_name": "Kowalska",
  "picture": "https://cdn.1g.pl/avatars/84213.webp",
  "email": "anna.kowalska@example.com",
  "email_verified": true
}
PoleZakresUwagi
subzawszeStały numer konta. Po nim rozpoznajesz powracającego — e-mail wolno zmienić, ten numer nie.
isszawszeKto wystawił: https://1g.pl.
name, given_name, family_nameprofilMoże być puste, jeśli użytkownik nie uzupełnił profilu.
pictureprofilnull, gdy nie ma awatara.
emailemailAdres z konta.
email_verifiedemailMówimy wprost, czy potwierdziliśmy ten adres.
Nie wpuszczaj nikogo na podstawie samego email Jeśli email_verified jest false, a Ty łączysz konta po adresie, ktoś może wpisać cudzy e-mail u nas i wejść na cudze konto u Ciebie. Łącz po sub, a e-mail traktuj jako dane pomocnicze.

Adresy punktów

PunktMetodaDo czego
https://1g.pl/api/oauth/authorize.phpGETEkran zgody. Tu przenosisz użytkownika.
https://1g.pl/api/oauth/token.phpPOSTKod → token. Serwer–serwer. Sekret w polu formularza albo w nagłówku Authorization: Basic.
https://1g.pl/api/oauth/userinfo.phpGETDane konta. Token wyłącznie w nagłówku Authorization: Bearer.

Ważność

CoJak długoDlaczego tyle
kod autoryzacyjny60 sekund, jednorazowyTyle trwa przekierowanie i wymiana. Dłużej znaczyłoby tylko szersze okno dla kogoś, kto go podejrzy.
token dostępu30 dniAplikacja pobiera dane przy logowaniu, nie w kółko. Cofnięcie zgody unieważnia token natychmiast, nie po 30 dniach.

Błędy

KodCo się stało
invalid_clientNieznany client_id albo zły sekret. Odpowiedź jest ta sama w obu wypadkach — celowo, żeby nie dało się sprawdzać, które identyfikatory istnieją.
invalid_grantKod wygasł, został już użyty, przyszedł z innym redirect_uri albo bez poprawnego code_verifier.
invalid_scopeProsisz o zakres, którego nie ma w rejestracji aplikacji.
invalid_tokenToken wygasł, został odwołany albo konto przestało istnieć. Zacznij logowanie od nowa.
unsupported_response_typeCoś innego niż code. Przepływu z tokenem w adresie nie wystawiamy.
ekran błędu u nas, bez powrotuNieznany client_id albo niezarejestrowany redirect_uri. Nie odsyłamy wtedy nigdzie — odesłanie pod niesprawdzony adres byłoby przekazaniem kodu obcemu.

Częste pytania

Sekret mi wyciekł. Co teraz?

W panelu Moje integracje kliknij „Nowy sekret”. Stary przestaje działać w tej samej chwili — do czasu wgrania nowego u siebie nikt się nie zaloguje, ale osoby już zalogowane zostają, bo ich tokeny są od sekretu niezależne.

Mogę użyć tego w aplikacji mobilnej?

Tak, ale sekret musi zostać na Twoim serwerze — w aplikacji zainstalowanej na cudzym telefonie nic nie jest tajne. Aplikacja otwiera nasz ekran w przeglądarce systemowej, a wymianę kodu na token wykonuje Twoje zaplecze. PKCE jest wtedy obowiązkowe w praktyce, nie tylko z nazwy.

Użytkownik cofnął zgodę — dowiem się o tym?

Nie powiadamiamy o tym osobno. Zorientujesz się przy pierwszym zapytaniu o dane: dostaniesz invalid_token ze statusem 401. Wtedy po prostu poproś użytkownika o ponowne zalogowanie.

Ile aplikacji mogę mieć?

Dziesięć na jedno konto. Jeśli potrzebujesz więcej, napisz do nas.

Załóż aplikację