# oidc-token-hash

> oidc-token-hash validates (and generates) ID Token `_hash` claims such as `at_hash` or `c_hash`

Latest version **5.2.0** (published 2025-11-04) · MIT license · 0 weekly downloads

## Install

```sh
npm install oidc-token-hash
pnpm add oidc-token-hash
yarn add oidc-token-hash
bun add oidc-token-hash
```

## Health

**Score 53/100 (C)** — status: stable.

Positive: has types package; no vulnerabilities; has provenance; high maintenance score; high quality score.

Warnings: low downloads; no esm support.

Negative: stale.

## Facts

| | |
|---|---|
| Version | 5.2.0 |
| Published | 2025-11-04 |
| First published | 2016-09-17 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | separate (@types/oidc-token-hash) |
| Module format | CommonJS |
| Node | ^10.13.0 \|\| >=12.0.0 |
| Dependencies | 0 |
| Unpacked size | 8.8 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Provenance | attested (GitHub Actions) |
| GitHub stars | 23 |
| Author | Filip Skokan |
| Maintainers | panva |

## Links

- npm: https://www.npmjs.com/package/oidc-token-hash
- Repository: https://github.com/panva/oidc-token-hash
- Issues: https://github.com/panva/oidc-token-hash/issues
- npm.io page: https://npm.io/package/oidc-token-hash

## Recent versions

- 5.2.0 (latest) — 2025-11-04
- 5.1.1 — 2025-07-31
- 5.1.0 — 2025-02-21
- 5.0.3 — 2023-04-25
- 5.0.2 — 2023-04-08
- 5.0.1 — 2021-01-18
- 5.0.0 — 2019-11-26
- 4.0.0 — 2019-11-07
- 3.0.2 — 2019-02-01
- 3.0.1 — 2018-05-17
- 3.0.0 — 2018-05-15
- 2.0.0 — 2017-10-12
- 1.0.1 — 2016-09-18
- 1.0.0 — 2016-09-17

## README

# oidc-token-hash

oidc-token-hash validates (and generates) ID Token `_hash` claims such as `at_hash` or `c_hash`

> Its [`*_hash`] value is the base64url encoding of the left-most half of the hash of the octets of
> the ASCII representation of the `token` / `state` / `code` value, where the hash algorithm used is
> the hash algorithm used in the `alg` Header Parameter of the ID Token's JOSE Header. For instance,
> if the `alg` is `RS256`, hash the `token` / `state` / `code` value with SHA-256, then take the
> left-most 128 bits and base64url encode them. The `*_hash` value is a case sensitive string.

## Matrix

| JWS algorithm | used hash algorithm | Note |
| --- | --- | --- |
| HS256, RS256, PS256, ES256, ES256K | sha256 | |
| HS384, RS384, PS384, ES384 | sha384 | |
| HS512, RS512, PS512, ES512 | sha512 | |
| EdDSA w/ Ed25519 curve | sha512 | [connect/issues#1125](https://bitbucket.org/openid/connect/issues/1125) |
| EdDSA w/ Ed448 curve | shake256(m, 114) | [connect/issues#1125](https://bitbucket.org/openid/connect/issues/1125) |
| Ed25519 | sha512 | [connect/issues#1125](https://bitbucket.org/openid/connect/issues/1125) |
| Ed448 | shake256(m, 114) | [connect/issues#1125](https://bitbucket.org/openid/connect/issues/1125) |
| ML-DSA-44, ML-DSA-65, ML-DSA-87 | shake256(m, 64) | [connect/issues#1125](https://bitbucket.org/openid/connect/issues/1125) |

## Usage

Validating
```js
const oidcTokenHash = require('oidc-token-hash');

const access_token = 'YmJiZTAwYmYtMzgyOC00NzhkLTkyOTItNjJjNDM3MGYzOWIy9sFhvH8K_x8UIHj1osisS57f5DduL-ar_qw5jl3lthwpMjm283aVMQXDmoqqqydDSqJfbhptzw8rUVwkuQbolw';

oidcTokenHash.validate({ claim: 'at_hash', source: 'access_token' }, 'x7vk7f6BvQj0jQHYFIk4ag', access_token, 'RS256'); // => does not throw
oidcTokenHash.validate({ claim: 'at_hash', source: 'access_token' }, 'EGEAhGYyfuwDaVTifvrWSoD5MSy_5hZPy6I7Vm-7pTQ', access_token, 'EdDSA', 'Ed25519'); // => does not throw
oidcTokenHash.validate({ claim: 'at_hash', source: 'access_token' }, 'EGEAhGYyfuwDaVTifvrWSoD5MSy_5hZPy6I7Vm-7pTQ', access_token, 'Ed25519'); // => does not throw
oidcTokenHash.validate({ claim: 'at_hash', source: 'access_token' }, 'x7vk7f6BvQj0jQHYFIk4ag', 'foobar', 'RS256'); // => throws AssertionError, message: at_hash mismatch, expected w6uP8Tcg6K2QR905Rms8iQ, got: x7vk7f6BvQj0jQHYFIk4ag
```

Generating
```js
// access_token from first example
oidcTokenHash.generate(access_token, 'RS256'); // => 'x7vk7f6BvQj0jQHYFIk4ag'
oidcTokenHash.generate(access_token, 'HS384'); // => 'ups_76_7CCye_J1WIyGHKVG7AAs2olYm'
oidcTokenHash.generate(access_token, 'ES512'); // => 'EGEAhGYyfuwDaVTifvrWSoD5MSy_5hZPy6I7Vm-7pTQ'
oidcTokenHash.generate(access_token, 'Ed25519'); // => 'EGEAhGYyfuwDaVTifvrWSoD5MSy_5hZPy6I7Vm-7pTQ'
oidcTokenHash.generate(access_token, 'EdDSA', 'Ed25519'); // => 'EGEAhGYyfuwDaVTifvrWSoD5MSy_5hZPy6I7Vm-7pTQ'
oidcTokenHash.generate(access_token, 'Ed448'); // => 'jxsy68_eG9-91VnHsZ2VnCr_WqDMv4nspiSuUPRdNZnv1y5lNV3rPVYYWNiY_TbUB1JRwlgiDTzZ'
oidcTokenHash.generate(access_token, 'EdDSA', 'Ed448'); // => 'jxsy68_eG9-91VnHsZ2VnCr_WqDMv4nspiSuUPRdNZnv1y5lNV3rPVYYWNiY_TbUB1JRwlgiDTzZ'
```

## Changelog
- 5.2.0 - add support ML-DSA JWS Algorithm Identifiers
- 5.1.1 - remove conditional shake256 check
- 5.1.0 - add support for Ed25519 and Ed448 JWS Algorithm Identifiers
- 5.0.2 - avoid use of deprecated String.prototype.substr
- 5.0.1 - use `base64url` native encoding in Node.js when available
- 5.0.0 - fixed `Ed448` and `shake256` to use 114 bytes output
- 4.0.0 - using `sha512` for `Ed25519` and `shake256` for `Ed448`, refactored API, removed handling of `none` JWS alg
- 3.0.2 - removed `base64url` dependency
- 3.0.1 - `base64url` comeback
- 3.0.0 - drop lts/4 support, replace base64url dependency
- 2.0.0 - rather then assuming the alg based on the hash length `#valid()` now requires a third
  argument with the JOSE header `alg` value, resulting in strict validation
- 1.0.0 - initial release

---
_Source: https://npm.io/package/oidc-token-hash · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
