As more of our services leverage Sourcegraph Accounts Management System (SAMS) for user authentication a need has arisen for secure long-lived credentials for automation access which can’t be served by the current session based authentication due to the enforced session expiry.

SAMS Service Access Tokens build on our existing token mechanisms used for SAMS M2M (machine-to-machine) authentication and authorization to allow users to generate service scoped access tokens with the same permissions as the user.

Adoption of this mechanism was originally proposed in https://docs.google.com/document/d/1e_lpAYT3JiViNsmFKTA9yWmNc_46dRhMKWDG2NNmknA/edit?tab=t.0#heading=h.xfxvegu9cqpz

Service access tokens are currently integrated into:

Token Management

Tokens are created in SAMS on behalf of the user by a client service using the Service Access Token RPCs defined in the SAMS SDK. Client services require the correct scopes SAMS token scope specification to create, read, and delete tokens. A client can only create service access tokens for services granted via scopes e.g. sams::service_access_token.analytics::write allows creating service access tokens for the Sourcegraph Analytics service. Service access token can only have scopes that belong to the same service, e.g. analytics::analytics::read when the service is analytics.

Token Authentication

Servers should check the validity of an access token and the scopes associated with it using token introspection - this is provided in the SAMS SDK (‣) via (TokenServiceV1).IntrospectToken. See: Authentication: token introspection

If a token is a Service Access Token the output of IntrospectToken will include the UserID of the user who created the token. Servers should ensure that any action performed is done so with the correct permissions associated with the user.

Token Authorization

Servers should check the scopes granted to the token match the required scopes to interact with the server.

Servers should integrate (scopes.AllowedScopes).Contains or (scopes.Scope).Match to validate incoming requested scopes according to strategies outlined in SAMS token scope specification, for example to check for analytics::analytics::read :

result, err := tokens.IntrospectToken(ctx, token)
if err != nil {
	// ...
}
if !result.Active {
	// ...
}

requiredSamsScope := scopes.ToScope(services.Analytics, "analytics", scopes.ActionRead)
// Validate the scopes on the token introspection result
if !result.Scopes.Match(requiredSamsScope) {
   // ...
}

Future improvements