Signup

The signup API provides an ID-porten verified registration flow. Users authenticate with their Norwegian national identity (personnummer) via ID-porten, select an organization they represent, and complete account creation. The flow supports both new users and existing users adding a new organization.

All signup endpoints are public (no authentication required) and rate-limited.

Endpoints

Method Endpoint Description
POST /public/v2/auth/signup/authorize Initiate ID-porten authorization
GET /public/v2/auth/signup/callback Handle ID-porten callback (browser-only)
POST /public/v2/auth/signup Complete signup

Signup Flow

The signup process is a three-step flow:

  1. Authorize — Your app calls POST /public/v2/auth/signup/authorize to get an ID-porten authorization URL and a session key.
  2. Callback — Open the authorization URL in a popup window. After the user authenticates with ID-porten, the popup posts a message back to your app with the session key, the user’s name, and their authorized organizations.
  3. Complete — Your app calls POST /public/v2/auth/signup with the session key, selected organization, and (for new users) email and password to create the account.

The session is stored server-side with a 15-minute TTL and is single-use.


Initiate Authorization

POST /public/v2/auth/signup/authorize

Returns an ID-porten authorization URL and a session key. Rate limited to 10 requests per hour.

Query Parameters

Parameter Type Required Description
provider string No Identity provider. Currently only id-porten (default)

Response

{
  "authorization_url": "https://login.idporten.no/authorize?...",
  "session_key": "abc123def456"
}

Open authorization_url in a popup window. The session_key is used in subsequent steps to reference the authenticated session.

Error Responses

Status Description
400 Unsupported provider
429 Rate limit exceeded (10 per hour)

Handle Callback

GET /public/v2/auth/signup/callback

Handles the OAuth callback from ID-porten. This endpoint is called by the browser as a redirect from ID-porten — it is not called directly by your application. Rate limited to 20 requests per hour.

On success, the endpoint returns an HTML page that posts a window.postMessage to the opener window and closes itself. On failure, it posts an error message instead.

Query Parameters

Parameter Type Required Description
provider string No Identity provider. Currently only id-porten (default)
code string Yes Authorization code from ID-porten (added by the OAuth redirect)
state string Yes State parameter from the OAuth redirect

Success Message

The popup posts a message to window.opener with this shape:

{
  "type": "ID_PORTEN_SIGNUP_VERIFIED",
  "session_key": "abc123def456",
  "given_name": "Ola",
  "family_name": "Nordmann",
  "is_existing_user": false,
  "organizations": [
    {
      "id": 101,
      "name": "Nordmann AS",
      "organization_number": "123456789",
      "already_registered": false
    }
  ]
}
Field Type Description
type string Always ID_PORTEN_SIGNUP_VERIFIED
session_key string The session key to use when completing signup
given_name string User’s first name from ID-porten
family_name string User’s last name from ID-porten
is_existing_user boolean Whether the identity matches an existing Snapbooks user
organizations array Organizations the user can represent via Altinn

Each organization object:

Field Type Description
id integer Snapbooks organization ID
name string Organization name
organization_number string Norwegian organization number
already_registered boolean Whether this organization already has a Snapbooks client account

Error Message

{
  "type": "ID_PORTEN_SIGNUP_ERROR",
  "error": "An unexpected error occurred"
}

Complete Signup

POST /public/v2/auth/signup

Completes the signup by creating a user account (if needed) and a client account for the selected organization. Rate limited to 50 requests per hour.

Request Body

Field Type Required Description
session_key string Yes Session key from the callback step
organization_id integer Yes ID of the organization to register (must be in the session’s authorized list)
email string Conditional Email address. Required for new users
password string Conditional Password. Required for new users

For existing users (where is_existing_user was true in the callback message), only session_key and organization_id are required. The user is logged in automatically.

For new users, email and password are also required. If the email belongs to an existing account without an ID-porten identity, the user must provide the correct password to link the identity.

Example Request (New User)

{
  "session_key": "abc123def456",
  "organization_id": 101,
  "email": "ola@nordmann.no",
  "password": "securePassword123"
}

Example Request (Existing User)

{
  "session_key": "abc123def456",
  "organization_id": 101
}

Response

{
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "user": {
    "id": 42,
    "first_name": "Ola",
    "last_name": "Nordmann",
    "email": "ola@nordmann.no"
  },
  "status": true,
  "message": "User created successfully"
}

The response includes:

Field Type Description
token string JWT access token
user object The created or existing user
status boolean Always true on success
message string "User created successfully" for new users, "Organization added successfully" for existing users

A refresh_token cookie is also set as an HTTP-only secure cookie.

Error Responses

Status Description
400 Missing session_key or organization_id
400 Invalid or expired session (sessions expire after 15 minutes)
400 Organization not in the session’s authorized list
400 Organization already registered
400 Missing email or password for new user
400 Password is too weak
400 A user with this email already exists (with a different ID-porten identity)
400 Incorrect password (when linking to existing email account)
400 This identity is already registered
429 Rate limit exceeded (50 per hour)

Notes

  • The signup flow uses ID-porten for identity verification. The user’s personnummer is stored as an HMAC-SHA256 hash for privacy.
  • Organizations are fetched from Altinn during the callback step. Only organizations the user can represent (via Altinn authorized parties) are available for selection.
  • Organizations that already have a Snapbooks client account cannot be registered again.
  • The signup session is single-use — once POST /public/v2/auth/signup succeeds, the session is deleted.
  • After signup, ID-porten tokens are stored to provide immediate Altinn access without requiring the user to authenticate again.