npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@saturate/mitid

v0.3.1

Published

CLI and library for authenticating with Denmark's MitID identity system

Readme

mitid

CLI and Node.js library for authenticating with Denmark's MitID test environment; without a browser.

Why?

MitID's browser widget carries the same anti-automation protections in the pre-production test environment (pp.mitid.dk) as in production. It renders inside a cross-origin iframe, includes debugger traps, and detects automated browsers. This makes sense in production, but makes automated testing unnecessarily difficult. Standard tools like Puppeteer, Playwright, and Selenium can't interact with the widget, and Chrome DevTools Protocol (CDP) connections cause it to freeze.

This tool sidesteps the widget entirely by implementing the MitID authentication protocol directly over HTTP; the same custom SRP-6a key exchange, the same API endpoints, just without the iframe. Combined with the MitID test simulator API for auto-approving login requests, it enables fully automated MitID authentication for your test workflows.

Install

npm install -g @saturate/mitid

Or use directly with npx:

npx @saturate/mitid --help

Quick start

# Look up a test identity
mitid info <username>

# Save it for quick access
mitid save <username> myuser

# See all saved identities
mitid list

Usage

Manual browser testing

You log in through your browser, the CLI handles the MitID approval step automatically:

# Auto-approve the next login attempt
mitid approve myuser

# Or keep it running to approve every login attempt
mitid approve myuser --watch

When MitID asks you to approve in the app, the CLI does it automatically via the simulator.

Fully automated login

No browser needed. Single command that handles both login and approval. Outputs JSON to stdout with cookies, tokens, and metadata. Progress goes to stderr so piping works cleanly:

# Single command - login + auto-approve:
mitid login myuser https://your-service.example.com/login/mitid

Output is JSON:

{
  "provider": "Criipto",
  "finalUrl": "https://your-service.example.com/callback",
  "cookies": { "session": "abc123", "token": "eyJ..." },
  "body": { "access_token": "eyJ...", "refresh_token": "..." }
}

The body field is always present. Parsed as JSON when possible, raw string otherwise. Extract what you need with jq:

# Get an access token
mitid login myuser <url> | jq -r '.body.access_token'

# Get cookies as a string for curl
mitid login myuser <url> | jq -r '.cookies | to_entries | map("\(.key)=\(.value)") | join("; ")'

# If you need to approve separately (e.g. different machine):
mitid login myuser <url> --no-approve
# Then in another terminal: mitid approve myuser

AI agent / browser automation

For AI agents (Claude, Cursor, etc.) controlling a browser via Chrome DevTools MCP, Playwright, or similar; where the MitID widget refuses to render:

  1. Run mitid login <user> <service-login-url> to get JSON output
  2. Parse the JSON for cookies or access tokens
  3. Inject the cookies into the automated browser, or use the access token as a Bearer token
// Example: inject cookies into an automated browser
const cookies = { "SessionCookie": "<value>", "AuthToken": "<value>" };
for (const [name, value] of Object.entries(cookies)) {
  document.cookie = `${name}=${value}; path=/`;
}
location.reload();

Full guide

mitid guide

Prints detailed workflow instructions for all use cases including library usage.

Commands

| Command | Description | |---------|-------------| | mitid info <query> | Show identity details (username, UUID, CPR, authenticators) | | mitid login <query> <url> | Login and auto-approve in one step. Outputs JSON. Use --no-approve to approve separately | | mitid approve <query> | Manually approve a pending MitID login via the simulator. Use --watch to keep approving | | mitid save <query> [alias] | Save an identity for quick access. Use --note to annotate | | mitid list | Show all saved identities | | mitid export | Export saved identities as JSON (pipe-friendly) | | mitid import <file> | Import identities from a JSON file (or - for stdin) | | mitid remove <alias> | Remove a saved identity | | mitid open <query> | Open the simulator in the default browser | | mitid copy <query> | Copy the simulator URL to clipboard | | mitid json <query> | Output full identity data as JSON | | mitid providers | List supported MitID broker providers | | mitid guide | Show detailed usage guide |

Query can be a MitID username, UUID, CPR number, or a saved alias.

Sharing identities with your team

# Export your saved identities
mitid export > identities.json

# A colleague imports them
mitid import identities.json

# Or pipe directly
mitid export | ssh colleague "mitid import -"

Library usage

import { MitIDClient, login, approve, resolve } from '@saturate/mitid';

// Look up a test identity
const { identity, codeApp } = await resolve('TestUser123');
console.log(identity.identityName, identity.cprNumber);

// Full login flow (returns cookies, response body, and metadata)
const result = await login(
  'TestUser123',
  'https://your-service.example.com/login/mitid',
  console.log // status callback
);
console.log(result.cookies);  // session cookies
console.log(result.body);     // response body (may contain tokens)

// Auto-approve a pending login
await approve(identity.identityId, codeApp.authenticatorId);

// Or use the MitID client directly
const client = new MitIDClient('https://pp.mitid.dk');
await client.init(clientHash, authenticationSessionId);
await client.identifyAndGetAuthenticators('TestUser123');
await client.authenticateWithApp();
const authorizationCode = await client.finalize();

Environment

By default, the CLI targets MitID's pre-production environment (pp.mitid.dk). To use production:

mitid info <query> --env prod

How it works

The tool replaces two things that normally require a browser and a phone:

  1. The MitID browser widget; replaced by a direct HTTP implementation of the MitID authentication protocol (custom SRP-6a with 4096-bit parameters)
  2. The MitID app approval; replaced by the MitID test simulator API which auto-approves with the test PIN
Service login URL
  → OAuth redirect chain → Broker (Criipto/NemLog-in/etc.)
  → Extract "aux" from broker page
  → MitID core API: identify user → APP auth (push to simulator)
  → Poll for approval → SRP-6a key exchange → Finalize
  → Authorization code → Broker callback → Session cookies / tokens

The aux (auxiliary data) is a base64-encoded JSON blob that the broker passes to the MitID widget. It contains the authenticationSessionId and a checksum needed to start the authentication. Each broker delivers it differently (JSON endpoint, inline JS, POST response), which is why providers need different extraction logic.

Supported providers

The login flow auto-detects your MitID broker from the OAuth redirect chain:

| Provider | Detection | Used by | |----------|-----------|---------| | Criipto | *.idura.broker or criipto.* URLs | Services using Criipto Verify | | NemLog-in | nemlog-in.mitid.dk | Danish public services (borger.dk, skat.dk, e-boks, etc.) | | Direct MitID | mitid.dk/administration | mitid.dk self-service portal |

mitid providers   # list all supported providers

Adding a provider

If your service uses a broker not listed above, you can add a custom provider. A provider needs two things:

  1. detect - identify the broker from the URL/HTML after OAuth redirects
  2. bootstrap - extract the MitID aux (session ID + checksum) and return an exchange callback
import { login } from '@saturate/mitid';
import type { Provider, CookieJar } from '@saturate/mitid';

const myProvider: Provider = {
  name: 'MyBroker',

  detect: (url, body) => url.includes('my-broker.example.com'),

  async bootstrap(url, body, cookies) {
    // Extract aux from your broker's page (HTML scraping, JSON endpoint, etc.)
    const aux = /* ... */;

    return {
      clientHash: Buffer.from(aux.coreClient.checksum, 'base64').toString('hex'),
      authenticationSessionId: aux.parameters.authenticationSessionId,
      apiBaseUrl: 'https://pp.mitid.dk', // or extract from aux.parameters.apiUrl
      cookies,
      exchange: async (authCode: string, cookies: CookieJar) => {
        // Return the URL to redirect to with the auth code
        return { redirectUrl: `https://my-broker.example.com/callback?code=${authCode}` };
      },
    };
  },
};

// Use it
const result = await login('username', 'https://my-service.com/login', console.log, myProvider);

PRs adding new providers to src/providers.ts are welcome.

Requirements

  • Node.js 18+

Acknowledgments

The MitID protocol implementation is ported from Hundter/MitID-BrowserClient (MIT), a Python implementation that reverse-engineered the MitID browser client. This project is a TypeScript/Node.js port with added simulator auto-approval and CLI tooling.

License

MIT