Documentation
¶
Overview ¶
Package githubapp is client middleware to authenticate to GitHub as an app.
Index ¶
- Constants
- type Error
- type InstallationToken
- type JWT
- type Option
- func Options(options ...Option) Option
- func WithEndpoint(endpoint string) Option
- func WithInstallationID(id uint64) Option
- func WithOwner(username string) Option
- func WithPermissions(permissions ...string) Option
- func WithRepositories(repos ...string) Option
- func WithRoundTripper(next http.RoundTripper) Option
- func WithUserAgent(ua string) Option
- type Transport
- func (t *Transport) AppID() uint64
- func (t *Transport) AppName() string
- func (t *Transport) BotCommitterEmail() string
- func (t *Transport) BotUsername() string
- func (t *Transport) InstallationID() uint64
- func (t *Transport) InstallationToken(ctx context.Context) (InstallationToken, error)
- func (t *Transport) JWT(ctx context.Context) (JWT, error)
- func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error)
- func (t *Transport) ScopedPermissions() map[string]string
- type WebHook
Constants ¶
const ( // ErrWebHookMethod is returned by [VerifyWebHookRequest] when a request method // is not PUT. ErrWebHookMethod = Error("githubapp(webhook): method not supported") // ErrWebHookContentType is returned by [VerifyWebHookRequest] when a request // content type is not 'application/json'. ErrWebHookContentType = Error("githubapp(webhook): unsupported content type") // ErrWebHookRequest is returned by [VerifyWebHookRequest] when request is invalid // or missing GitHub specific webhook metadata headers (X-GitHub-Event, X-GitHub-Hook-ID etc.). ErrWebHookRequest = Error("githubapp(webhook): invalid request") // ErrWebhookSignature is returned by [VerifyWebHookRequest] when the signature does not match. ErrWebhookSignature = Error("githubapp(webhook): HMAC-SHA256 signature is invalid") )
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Error ¶
type Error string
Error is immutable error representation.
Error strings themselves are NOT part of semver compatibility guarantees. Use exported symbols instead of directly using error strings.
type InstallationToken ¶
type InstallationToken struct { // Installation access token. Typically starts with "ghs_". Token string `json:"token,omitempty" yaml:"token,omitempty"` // GitHub app ID. AppID uint64 `json:"app_id,omitempty" yaml:"appID,omitempty"` // GitHub app name. AppName string `json:"app_name,omitempty" yaml:"appName,omitempty"` // Installation ID for the app. InstallationID uint64 `json:"installation_id,omitempty" yaml:"installationID,omitempty"` // GitHub API endpoint. This is also used for token revocation. // If omitted, assume the default value of "https://api.githhub.com/". Server string `json:"server,omitempty" yaml:"server,omitempty"` // UserAgent used to fetch this installation access token. UserAgent string `json:"user_agent,omitempty" yaml:"user_agent,omitempty"` // Token exp time. Exp time.Time `json:"exp,omitempty" yaml:"exp,omitempty"` // Installation owner. This is owner of the installation. Owner string `json:"owner,omitempty" yaml:"owner,omitempty"` // Repositories which can be accessed with the token. This may be empty // if a scoped token is not requested. In such cases, token will have access to all // repositories accessible by the installation. Repositories []string `json:"repositories,omitempty" yaml:"repositories,omitempty"` // Permissions available for the token. This may be omitted if scoped permissions are not // requested. In such cases token has all permissions available to the installation. Permissions map[string]string `json:"permissions,omitempty" yaml:"permissions,omitempty"` // BotUsername is app's github username. BotUsername string `json:"bot_username,omitempty" yaml:"bot_username,omitempty"` // BotCommitterEmail is committer email to use to attribute commits to the bot. // This is in the form "<user-id>+<app-name>[bot]@users.noreply.github.com". BotCommitterEmail string `json:"bot_committer_email,omitempty" yaml:"bot_committer_email,omitempty"` }
InstallationToken is an installation access token from GitHub.
func NewInstallationToken ¶
func NewInstallationToken(ctx context.Context, appid uint64, signer crypto.Signer, opts ...Option) (InstallationToken, error)
NewInstallationToken returns new installation access token. This takes same options as Transport.
func (*InstallationToken) IsValid ¶
func (t *InstallationToken) IsValid() bool
IsValid checks if InstallationToken is valid for at-least 60 seconds.
func (*InstallationToken) LogValue ¶
func (t *InstallationToken) LogValue() slog.Value
LogValue implements log/slog.LogValuer.
type JWT ¶
type JWT struct { // JWT token. Token string `json:"token" yaml:"token"` // GitHub app ID. AppID uint64 `json:"id,omitempty" yaml:"id,omitempty"` // GitHub app name. AppName string `json:"app,omitempty" yaml:"app,omitempty"` // Token exp time. Exp time.Time `json:"exp,omitempty" yaml:"exp,omitempty"` // Token issue time. IssuedAt time.Time `json:"iat,omitempty" yaml:"iat,omitempty"` }
JWT is JWT token used to authenticate as app.
func NewJWT ¶
NewJWT returns new JWT bearer token signed by the signer.
Returned JWT is valid for at least 5min. Ensure that your machine's clock is accurate.
- Unlike NewTransport, this does not validate app id and signer. This simply mints the JWT as required by GitHub app authentication.
- RSA keys of length less than 2048 bits are not supported.
- Only RSA keys are supported. Using ECDSA, ED25519 or other keys will return error.
type Option ¶
type Option interface {
// contains filtered or unexported methods
}
Option is option to apply for Transport.
func Options ¶
Options takes a variadic slice of Options and returns a single Options which includes all the given options. This is useful for sharing presets. If conflicting options are specified, last-specified wins. As a special case, if no options are specified or all specified options are nil, this will returns nil.
func WithEndpoint ¶
WithEndpoint configures Transport to use custom REST API(v3) endpoint. for authenticating as app, obtaining installation metadata and creating installation access tokens. This MUST be REST(v3) endpoint even though a client might be using GitHub GraphQL API.
When not specified or empty, "https://api.github.com/" is used.
func WithInstallationID ¶
WithInstallationID configures Transport to use installation id specified.
This is useful if it is required to access all repositories available for an installation without specifying them individually or if building Transport from data provided by WebHook.
func WithPermissions ¶
WithPermissions configures permission scopes. This is useful when app has a broader set of permissions, a scoped access token is required.
Permissions MUST be specified in "<scope>:<access>" or "<scope>=<access>" format. Where scope is permission scope like "issues" and access can be one of "read", "write" or "admin".
For example, to request permissions to write issues and pull request can be specified as,
githubapp.WithPermissions("issues:write", "pull_requests:write")
func WithRepositories ¶
WithRepositories configures Transport to use installation for repos specified. Unlike other installation options, this can be used multiple times.
func WithRoundTripper ¶
func WithRoundTripper(next http.RoundTripper) Option
WithRoundTripper configures Transport to use next as next http.RoundTripper.
This can be used to further customize headers, add logging or retries. This only applies to authentication API calls and not the http client using the Transport.
func WithUserAgent ¶
WithUserAgent configures user agent header to use for token related API requests.
Typically, Transport which implements http.RoundTripper will re-use the User-Agent header specified by the http.Request. However, when building the Transport several HTTP requests need to be made to verify and configure it. User agent specified here will be used during bootstrapping. This is also as fallback for token renewal requests.
type Transport ¶
type Transport struct {
// contains filtered or unexported fields
}
Transport provides a http.RoundTripper by wrapping an existing http.RoundTripper and provides GitHub Apps authenticating as a GitHub App or as an GitHub app installation.
'Authorization' header is automatically populated with a suitable installation token or JWT token for all requests. If it already exists, it is ignored. Token renewal requests will always override 'Accept' and "X-GitHub-Api-Version" headers.
func NewTransport ¶
func NewTransport(ctx context.Context, appid uint64, signer crypto.Signer, opts ...Option) (*Transport, error)
NewTransport creates a new Transport for authenticating as an app/installation.
How Transport authenticates depends on installation options specified.
- If no installation options are specified, then Transport can only authenticate as app (using JWT). This is not something you want typically, as a very limited number of actions like accessing available installations.
- Use WithInstallationID to have access to all permissions available to the installation including organization scopes and repositories. This can be used together with WithPermissions to limit the scope of access tokens. A typical example would be to close all stale issues for all repositories in an organization. This task does not require access to code, thus "issues:write" permission should be sufficient.
- Use WithOwner if your app has only access to organization/user permissions and none of the repositories belonging to the owner. A typical example would be an app, which manages self-hosted runners in an organization or manages organization level projects.
- Use WithRepositories if your app intends to access only a set of repositories. Do note that if app has access to organization permissions, they will also be available to the access token, unless limited with WithPermissions.
- WithPermissions can be used to limit the scope of permissions available to the access token.
Access token and JWT are automatically refreshed whenever required.
If only installation access token or JWT is required but not the round tripper, use NewInstallationToken or NewJWT respectively.
func (*Transport) BotCommitterEmail ¶
BotCommitterEmail returns the GitHub app's no-reply email to use for git metadata.
func (*Transport) BotUsername ¶
BotUsername returns the GitHub app's username.
func (*Transport) InstallationID ¶
InstallationID returns the GitHub installation id. If not repositories or organizations are configured, This will return 0.
func (*Transport) InstallationToken ¶
func (t *Transport) InstallationToken(ctx context.Context) (InstallationToken, error)
InstallationToken returns a new installation access token. This always returns a new token, thus callers can safely revoke the token whenever required.
func (*Transport) ScopedPermissions ¶
ScopedPermissions returns permissions configured for the transport. This is not the same as app permissions. This will return nil if no scoped permissions are set.
type WebHook ¶
type WebHook struct { // ID is webhook ID received in X-GitHub-Hook-ID header. ID string // Event is event type like "issues" received in X-GitHub-Event header. Event string // Payload is payload received in POST. Payload []byte // DeliveryID is a unique delivery id received in X-GitHub-DeliveryID header. DeliveryID string // Signature is HMAC hex digest of the request body with the prefix "sha256=". // This is populated from X-Hub-Signature-256 header. Signature string // GitHub app installation ID. This can be used by WithInstallationID // for building Transport applicable for the installation in the hook event. InstallationID uint64 // InstallationType can be repo|user|org. InstallationType string }
WebHook is returned by VerifyWebHookRequest upon successful verification of the webhook request. It contains all the webhook payloads with additional info from headers to detect GitHub app installation.
func VerifyWebHookRequest ¶
VerifyWebHookRequest is a simple function to verify webhook HMAC-SHA256 signature.
This functions assumes that headers are canonical by default and have not been modified. Only HMAC-SHA256 signatures are considered for verification and SHA1 signature headers are ignored.
Typically, HMAC secret would be []byte, but as it may be updated via web interface, which can only accept strings. Returned value is only valid if error is nil.
- ErrWebHookRequest is returned when request is invalid and is missing or malformed headers like 'X-GitHub-Event', 'X-Hub-Signature-256' and more.
- ErrWebHookMethod is returned when webhook request is not a PUT request.
- ErrWebHookContentType is returned when content type header is not set to 'application/json'. Though GitHub supports 'application/x-www-form-urlencoded', it is NOT supported by this library.
- ErrWebhookSignature is returned when signature does not match.
An example HTTP handler which returns appropriate http status code is shown below.
mux.HandleFunc("/webhook", func(w http.ResponseWriter, r *http.Request) { webhook, err := githubapp.VerifyWebHookRequest(secret, r) if err != nil { switch { case errors.Is(err, githubapp.ErrWebhookSignature): w.WriteHeader(http.StatusUnauthorized) case errors.Is(err, githubapp.ErrWebHookRequest): w.WriteHeader(http.StatusBadRequest) case errors.Is(err, githubapp.ErrWebHookContentType): w.WriteHeader(http.StatusUnsupportedMediaType) case errors.Is(err, githubapp.ErrWebHookMethod): w.WriteHeader(http.StatusMethodNotAllowed) default: // This is non-reachable code. w.WriteHeader(http.StatusNotImplemented) } _, _ = w.Write([]byte(err.Error())) return } // Do something with webhook, for example, put it in SQS or PubSub. err = doSomething(r.Context(), webhook) if err != nil { w.WriteHeader(http.StatusInternalServerError) return } // Return HTTP status 2xx. w.WriteHeader(http.StatusAccepted) })
Source Files
¶
Directories
¶
Path | Synopsis |
---|---|
examples
|
|
app-token
An example CLI which can fetch installation tokens for a GitHub app.
|
An example CLI which can fetch installation tokens for a GitHub app. |
go-github
Module
|
|
go-github-readme
Module
|
|
internal
|
|
api
Package api holds types and methods to serialize and deserialize requests to and from GitHub API.
|
Package api holds types and methods to serialize and deserialize requests to and from GitHub API. |
testkeys
Package testkeys generates ephemeral test keys.
|
Package testkeys generates ephemeral test keys. |