TokenData#

pydantic model gafaelfawr.models.token.TokenData#

Data about a token stored in Redis.

This holds all the token information stored in Redis, and thus all the token information required to support authentication decisions and (currently) user information queries. It should not be used directly as a response model; for that, see TokenInfo and TokenUserInfo.

Parameters:

data (Any) –

Show JSON schema
{
   "title": "TokenData",
   "description": "Data about a token stored in Redis.\n\nThis holds all the token information stored in Redis, and thus all the\ntoken information required to support authentication decisions and\n(currently) user information queries.  It should not be used directly as a\nresponse model; for that, see `TokenInfo` and `TokenUserInfo`.",
   "type": "object",
   "properties": {
      "username": {
         "description": "User to whom the token was issued",
         "examples": [
            "someuser"
         ],
         "maxLength": 64,
         "minLength": 1,
         "title": "Username",
         "type": "string"
      },
      "name": {
         "anyOf": [
            {
               "minLength": 1,
               "type": "string"
            },
            {
               "type": "null"
            }
         ],
         "default": null,
         "examples": [
            "Alice Example"
         ],
         "title": "Preferred full name"
      },
      "email": {
         "anyOf": [
            {
               "minLength": 1,
               "type": "string"
            },
            {
               "type": "null"
            }
         ],
         "default": null,
         "examples": [
            "alice@example.com"
         ],
         "title": "Email address"
      },
      "uid": {
         "anyOf": [
            {
               "minimum": 1,
               "type": "integer"
            },
            {
               "type": "null"
            }
         ],
         "default": null,
         "examples": [
            4123
         ],
         "title": "UID number"
      },
      "gid": {
         "anyOf": [
            {
               "minimum": 1,
               "type": "integer"
            },
            {
               "type": "null"
            }
         ],
         "default": null,
         "description": "GID of primary group. If set, this will also be the GID of one of the groups of which the user is a member.",
         "examples": [
            4123
         ],
         "title": "Primary GID"
      },
      "groups": {
         "anyOf": [
            {
               "items": {
                  "$ref": "#/$defs/TokenGroup"
               },
               "type": "array"
            },
            {
               "type": "null"
            }
         ],
         "default": null,
         "description": "Groups of which the user is a member",
         "title": "Groups"
      },
      "quota": {
         "anyOf": [
            {
               "$ref": "#/$defs/Quota"
            },
            {
               "type": "null"
            }
         ],
         "default": null,
         "title": "Quota"
      },
      "token_type": {
         "allOf": [
            {
               "$ref": "#/$defs/TokenType"
            }
         ],
         "description": "Class of token, chosen from:\n\n* `session`: An interactive user web session\n* `user`: A user-generated token that may be used programmatically\n* `notebook`: The token delegated to a Jupyter notebook for the user\n* `internal`: A service-to-service token used for internal sub-calls made as part of processing a user request\n* `service`: A service-to-service token used for internal calls initiated by services, unrelated to a user request\n",
         "examples": [
            "session"
         ],
         "title": "Token type"
      },
      "scopes": {
         "description": "Scopes of the token",
         "examples": [
            [
               "read:all",
               "user:token"
            ]
         ],
         "items": {
            "type": "string"
         },
         "title": "Token scopes",
         "type": "array"
      },
      "created": {
         "description": "Creation timestamp of the token in seconds since epoch",
         "examples": [
            1614986130
         ],
         "format": "date-time",
         "title": "Creation time",
         "type": "string"
      },
      "expires": {
         "anyOf": [
            {
               "format": "date-time",
               "type": "string"
            },
            {
               "type": "null"
            }
         ],
         "default": null,
         "description": "Expiration timestamp of the token in seconds since epoch",
         "examples": [
            1616986130
         ],
         "title": "Expiration time"
      },
      "token": {
         "allOf": [
            {
               "$ref": "#/$defs/Token"
            }
         ],
         "title": "Associated token"
      }
   },
   "$defs": {
      "NotebookQuota": {
         "description": "Notebook Aspect quota information for a user.",
         "properties": {
            "cpu": {
               "examples": [
                  4.0
               ],
               "title": "CPU equivalents",
               "type": "number"
            },
            "memory": {
               "examples": [
                  16.0
               ],
               "title": "Maximum memory use (GiB)",
               "type": "number"
            }
         },
         "required": [
            "cpu",
            "memory"
         ],
         "title": "NotebookQuota",
         "type": "object"
      },
      "Quota": {
         "description": "Quota information for a user.",
         "properties": {
            "api": {
               "additionalProperties": {
                  "type": "integer"
               },
               "default": {},
               "description": "Mapping of service names to allowed requests per 15 minutes.",
               "examples": [
                  {
                     "datalinker": 500,
                     "hips": 2000,
                     "tap": 500,
                     "vo-cutouts": 100
                  }
               ],
               "title": "API quotas",
               "type": "object"
            },
            "notebook": {
               "anyOf": [
                  {
                     "$ref": "#/$defs/NotebookQuota"
                  },
                  {
                     "type": "null"
                  }
               ],
               "default": null,
               "title": "Notebook Aspect quotas"
            }
         },
         "title": "Quota",
         "type": "object"
      },
      "Token": {
         "description": "An opaque token.\n\nNotes\n-----\nA token consists of two parts, a semi-public key that is used as the Redis\nkey, and a secret that is only present in the token returned to the user\nand the encrypted session in Redis.\n\nThe serialized form of a token always starts with ``gt-``, short for\nGafaelfawr token, to make it easier to identify these tokens in logs.\n\nThe serialized form encodes the secret in URL-safe base64 with the padding\nstripped off (because equal signs can be parsed oddly in cookies).",
         "properties": {
            "key": {
               "title": "Key",
               "type": "string"
            },
            "secret": {
               "title": "Secret",
               "type": "string"
            }
         },
         "title": "Token",
         "type": "object"
      },
      "TokenGroup": {
         "description": "Information about a single group.",
         "properties": {
            "name": {
               "examples": [
                  "g_special_users"
               ],
               "minLength": 1,
               "pattern": "^[a-zA-Z][a-zA-Z0-9._-]*$",
               "title": "Name of the group",
               "type": "string"
            },
            "id": {
               "anyOf": [
                  {
                     "type": "integer"
                  },
                  {
                     "type": "null"
                  }
               ],
               "default": null,
               "description": "Numeric GID may be unset, in which case the group still contributes to determining scopes, but may be ignored by services that require a GID. If Firestore is configured, a numeric GID will be allocated by Firestore if left unset when creating a token.",
               "examples": [
                  123181
               ],
               "title": "Numeric GID of the group"
            }
         },
         "required": [
            "name"
         ],
         "title": "TokenGroup",
         "type": "object"
      },
      "TokenType": {
         "description": "The class of token.",
         "enum": [
            "session",
            "user",
            "notebook",
            "internal",
            "service"
         ],
         "title": "TokenType",
         "type": "string"
      }
   },
   "required": [
      "username",
      "token_type",
      "scopes",
      "token"
   ]
}

Fields:
Validators:
field created: datetime [Optional]#

Creation timestamp of the token in seconds since epoch

field email: str | None = None#
Constraints:
  • min_length = 1

field expires: datetime | None = None#

Expiration timestamp of the token in seconds since epoch

field gid: int | None = None#

GID of primary group. If set, this will also be the GID of one of the groups of which the user is a member.

Constraints:
  • ge = 1

field groups: list[TokenGroup] | None = None#

Groups of which the user is a member

field name: str | None = None#
Constraints:
  • min_length = 1

field quota: Quota | None = None#
field scopes: list[str] [Required]#

Scopes of the token

Validated by:
field token: Token [Required]#
field token_type: TokenType [Required]#

Class of token, chosen from:

  • session: An interactive user web session

  • user: A user-generated token that may be used programmatically

  • notebook: The token delegated to a Jupyter notebook for the user

  • internal: A service-to-service token used for internal sub-calls made as part of processing a user request

  • service: A service-to-service token used for internal calls initiated by services, unrelated to a user request

field uid: int | None = None#
Constraints:
  • ge = 1

field username: str [Required]#

User to whom the token was issued

Constraints:
  • min_length = 1

  • max_length = 64

classmethod bootstrap_token()#

Build authentication data for the bootstrap token.

This token doesn’t exist in the backing store, so instead synthesize a ~gafaelfawr.models.token.TokenData object for it.

Returns:

Artificial data for the bootstrap token.

Return type:

TokenData

classmethod internal_token()#

Build authentication data for the internal token.

Similar to the bootstrap token, this does not exist in the backing store. It is used by background jobs internal to Gafaelfawr.

Returns:

Artificial data for the bootstrap token.

Return type:

TokenData

to_userinfo_dict()#

Convert to a dictionary for logging purposes.

This method converts only the TokenUserInfo portion of a token to a dictionary for logging purposes, excluding the username field (which is logged separately). It’s used when logging creation of new tokens to make a record of the user identity information included in the token (as opposed to retrieved dynamically from other sources such as LDAP or Firestore).

Returns:

Dictionary of information, roughly equivalent to calling dict(exclude_none=True) on the TokenUserInfo object, but ensuring that only its data is included even if called on a subclass such as TokenData.

Return type:

dict