This page covers the creds and gitcred packages, which sign a user in, keep the token fresh, store it and hand it to git. Read it if your tool lets users connect their own forge accounts.
creds.StartDeviceGrant and DeviceGrant.Poll run the OAuth device grant on GitHub and GitLab with your own OAuth application's client id. DeviceGrant.Close ends a pending grant early. On Gitea and Forgejo the library runs no device grant and answers CodeGrantUnsupported, so use a personal access token there.
For a static personal access token, a type of your own that implements forgeapi.CredentialSource is enough. Example in example_test.go declares one. creds.NewSource is the rotating source this library ships.
The Example in the creds package shows the whole flow. It renders the user code, polls at the interval the grant states, saves the record and builds a client on a source over that record.
creds.Source is a CredentialSource over one stored record. It refreshes a rotating token once the token's expiry is inside the refresh lead, which WithRefreshLead sets. One caller refreshes at a time while the others wait. A record it cannot refresh answers CodeReconnectRequired.
A refresh that learns the stored pair is dead writes a mark to the record's Usability:
UsabilitySpentwhen the forge rotated the pair and its answer carrying the new one could not be read.UsabilityReconnectRequiredwhen the forge refused the refresh.
Every reader of the store honours the mark, so a marked record is never handed over or refreshed. Token fails with CodeReconnectRequired and State answers CredReconnectRequired. A reconnect saves the record unmarked.
A rotation whose write to the store fails keeps the new pair in memory. That call fails and State answers CredRefreshDue. The next Token call in the same process stores the pair before it does anything else.
StoredToken reads the stored token and its State in one read of the store, and never refreshes, writes or waits on a refresh in flight. Use it when another part of your program owns refreshing, so a request only reads what is stored. It hands over a token that is valid, refresh-due or refreshing and not yet expired. It fails with CodeReconnectRequired where State answers CredReconnectRequired. A token whose refresh is due or in flight fails with a retryable transient error once it has expired, until a Token call renews it. Where a rotated pair waits in memory to replace the stored token, StoredToken hands over the pair's token, which the forge issued and the next Token call stores. It fails the same retryable way once the pair's token has expired or its refresh token has lapsed.
creds.OpenFileStore keeps every record in one file at mode 0600, in a directory at mode 0700 that the process owns.
Run exactly one refreshing process per store directory, the one that calls Token. The git credential helper only reads the store. Nothing detects a second refreshing process, and two of them can lose a rotated pair and leave the connection needing a reconnect.
gitcred.Helper.Serve answers one git credential-helper invocation from a creds.Store.
- A
gethands over the token of the connection whose web base URL has the remote's origin. Where several records share an origin, build the helper withgitcred.NewForand the keys git may be handed, read again on every invocation;gitcred.Newanswers from every key in the store, the first by key. - It declines an expired token or a marked record with one line naming the instance. For a marked record, the line says to reconnect.
- A
storeis ignored, and anerasekeeps the connection.
The helper never refreshes a token. Registering it with git, and the command line git runs it with, are yours to set up.