mbs-sso-js 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # mbs-sso-js 0.1.0
1
+ # mbs-sso-js 0.2.0
2
2
 
3
3
  Launch MBS SSO from HTML, React or React Native while keeping OAuth credentials on your application backend. MBS hosts login, enablement, NINAuth, OTP, password setup and consent. Opening a browser is not proof of authentication.
4
4
 
@@ -7,10 +7,10 @@ Launch MBS SSO from HTML, React or React Native while keeping OAuth credentials
7
7
  Install the versioned release from the npm registry once npm finishes processing it:
8
8
 
9
9
  ```sh
10
- npm install mbs-sso-js@0.1.1
10
+ npm install mbs-sso-js@0.2.0
11
11
  ```
12
12
 
13
- For local development, run `pnpm sdk:build` in the SSO repository, then install its `public/sdk/mbs-sso-js-0.1.0.tgz` file. Node helpers require Node 20+. React and React Native are optional peers; install them only for the adapter you use.
13
+ For local development, run `pnpm sdk:build` in the SSO repository, then install its `public/sdk/mbs-sso-js-0.2.0.tgz` file. Node helpers require Node 20+. React and React Native are optional peers; install them only for the adapter you use.
14
14
 
15
15
  ## HTML
16
16
 
@@ -41,7 +41,7 @@ Uses `Linking.openURL` to open the system browser. Use an absolute HTTPS start U
41
41
  `startUrl` is **your application's backend route**, not the MBS enrollment page. Implement `/auth/mbs/login` and `/auth/mbs/enablement` using the complete Express example in `examples/server.mjs`.
42
42
 
43
43
  1. Obtain a client ID and secret from the MBS team. Register your exact callback URL.
44
- 2. Set `MBS_SSO_BASE_URL=https://mbs.d3troit.dev`, `MBS_SSO_CLIENT_ID`, `MBS_SSO_CLIENT_SECRET`, `MBS_SSO_REDIRECT_URI`, and a strong `SESSION_SECRET` on your backend.
44
+ 2. Set `MBS_SSO_BASE_URL=https://api.mbs.gov.ng`, `MBS_SSO_CLIENT_ID`, `MBS_SSO_CLIENT_SECRET`, `MBS_SSO_REDIRECT_URI`, and a strong `SESSION_SECRET` on your backend.
45
45
  3. `createAuthorizationRequest()` creates random state, nonce and S256 PKCE values. Persist the returned transaction in your server session before redirecting to its `url` (`GET /oauth/authorize`).
46
46
  4. In your registered callback, atomically consume the pending transaction. `exchangeAuthorizationCode()` validates its lifetime, callback origin/path, unique state, error and code, then sends a form POST to `/oauth/token` with the original redirect URI, verifier and client credentials.
47
47
  5. Call `/oauth/userinfo` server-side and create your own application session. Tokens stay server-side. The helper does not verify an ID-token signature; do not use unverified ID-token claims to authenticate users. Use user info as in the example, or a configured OIDC library for ID-token verification.
@@ -53,3 +53,36 @@ The Express example uses a development memory session store and refuses producti
53
53
  The browser adapters know only your start URL. MBS backend improvements remain available in the hosted journey without an SDK update. Changes to the public authorization/token contract may require a new server helper release. Pin the SDK version and test against your registered client. Endpoint behavior is covered by contract tests; a full live sign-in still requires provisioned MBS credentials and NINAuth configuration.
54
54
 
55
55
  Native browser launch and return-link configuration require device validation; this release has not been tested in an iOS/Android emulator.
56
+
57
+ Production API base URL: `https://api.mbs.gov.ng`. Sandbox base URL: `https://mbs.d3troit.dev`. Use app credentials registered for the target environment. In MBS SSO Apps, **App ID** is the OAuth `client_id` (`MBS_SSO_CLIENT_ID`) and **App Secret** is the OAuth `client_secret` (`MBS_SSO_CLIENT_SECRET`). Keep the App Secret on your backend. Register your application’s exact callback URI.
58
+
59
+ ### Skip business search with an RC number
60
+
61
+ Pass `rcNumber: "216879"` to `startSso`, `MbsSsoButton`, or `mountButton`.
62
+ The SDK adds `rc_number` to your backend start URL. Your backend must forward
63
+ that value as `rcNumber` to `createAuthorizationRequest`. The authorization
64
+ service must preserve `rc_number` on its redirect to the SSO enrollment page
65
+ as a URL parameter. Provider-info describes the integrating application and is never used
66
+ as the taxpayer RC source. The enrollment page automatically searches CAC
67
+ and resolves an exact RC match, displaying Business Found or Business not found.
68
+ Users can select Start again to search manually. RC numbers are lookup hints;
69
+ NINAuth verification and authorization checks still apply.
70
+
71
+ ```jsx
72
+ <MbsSsoButton startUrl="/auth/mbs/enablement" rcNumber="216879" />
73
+ ```
74
+
75
+ ```js
76
+ await startSso({ startUrl: "/auth/mbs/enablement", rcNumber: "216879" });
77
+ // Backend start route:
78
+ const { url, transaction } = createAuthorizationRequest({
79
+ baseUrl,
80
+ clientId,
81
+ redirectUri,
82
+ flow: "enablement",
83
+ rcNumber: typeof req.query.rc_number === "string" ? req.query.rc_number : undefined,
84
+ });
85
+ ```
86
+
87
+ Omit `rcNumber` or pass an empty string to show manual business search.
88
+ Version 0.2.0 adds this option across browser, React, React Native and server helpers.
package/dist/browser.js CHANGED
@@ -5,6 +5,7 @@ export function mountButton(
5
5
  target,
6
6
  {
7
7
  startUrl,
8
+ rcNumber,
8
9
  label = "Continue with MBS",
9
10
  className = "",
10
11
  style = {},
@@ -32,7 +33,7 @@ export function mountButton(
32
33
  button.setAttribute("aria-busy", "true");
33
34
  status.textContent = "";
34
35
  try {
35
- await startSso({ startUrl, openUrl });
36
+ await startSso({ startUrl, openUrl, rcNumber });
36
37
  } catch (error) {
37
38
  status.textContent = "Could not open MBS SSO. Please try again.";
38
39
  onError?.(error);
package/dist/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  export interface StartOptions {
2
2
  startUrl: string;
3
+ rcNumber?: string;
3
4
  baseUrl?: string;
4
5
  openUrl?: (url: string) => unknown | Promise<unknown>;
5
6
  }
package/dist/index.js CHANGED
@@ -14,9 +14,12 @@ export function resolveStartUrl(startUrl, baseUrl) {
14
14
  return url.href;
15
15
  }
16
16
 
17
- export async function startSso({ startUrl, openUrl, baseUrl } = {}) {
17
+ export async function startSso({ startUrl, openUrl, baseUrl, rcNumber } = {}) {
18
18
  const browser = typeof window !== "undefined" ? window : undefined;
19
- const url = resolveStartUrl(startUrl, baseUrl ?? browser?.location?.href);
19
+ const target = new URL(resolveStartUrl(startUrl, baseUrl ?? browser?.location?.href));
20
+ if (rcNumber != null && String(rcNumber).trim())
21
+ target.searchParams.set("rc_number", String(rcNumber).trim());
22
+ const url = target.href;
20
23
  if (openUrl) await openUrl(url);
21
24
  else if (browser?.location?.assign) browser.location.assign(url);
22
25
  else throw new Error("Provide openUrl outside a browser.");
@@ -3,6 +3,7 @@ import { Linking, Pressable, Text, View } from "react-native";
3
3
  import { startSso } from "./index.js";
4
4
  export function MbsSsoButton({
5
5
  startUrl,
6
+ rcNumber,
6
7
  baseUrl,
7
8
  label = "Continue with MBS",
8
9
  style,
@@ -19,7 +20,7 @@ export function MbsSsoButton({
19
20
  setPending(true);
20
21
  setError("");
21
22
  try {
22
- await startSso({ startUrl, openUrl, baseUrl });
23
+ await startSso({ startUrl, openUrl, baseUrl, rcNumber });
23
24
  } catch (reason) {
24
25
  setError("Could not open MBS SSO. Please try again.");
25
26
  onError?.(reason);
package/dist/react.js CHANGED
@@ -3,6 +3,7 @@ import { createElement, useState } from "react";
3
3
  import { buttonStyle, startSso } from "./index.js";
4
4
  export function MbsSsoButton({
5
5
  startUrl,
6
+ rcNumber,
6
7
  baseUrl,
7
8
  children,
8
9
  label = "Continue with MBS",
@@ -21,7 +22,7 @@ export function MbsSsoButton({
21
22
  setPending(true);
22
23
  setError("");
23
24
  try {
24
- await startSso({ startUrl, openUrl, baseUrl });
25
+ await startSso({ startUrl, openUrl, baseUrl, rcNumber });
25
26
  } catch (reason) {
26
27
  setError("Could not open MBS SSO. Please try again.");
27
28
  onError?.(reason);
package/dist/server.d.ts CHANGED
@@ -11,6 +11,7 @@ export interface AuthorizationOptions {
11
11
  redirectUri: string;
12
12
  flow?: "login" | "enablement";
13
13
  scope?: string;
14
+ rcNumber?: string;
14
15
  now?: number;
15
16
  }
16
17
  export declare function createAuthorizationRequest(options: AuthorizationOptions): {
package/dist/server.js CHANGED
@@ -7,6 +7,7 @@ export function createAuthorizationRequest({
7
7
  redirectUri,
8
8
  flow = "login",
9
9
  scope = "profile",
10
+ rcNumber,
10
11
  now = Date.now(),
11
12
  }) {
12
13
  if (!clientId || !redirectUri) throw new Error("clientId and redirectUri are required.");
@@ -28,6 +29,8 @@ export function createAuthorizationRequest({
28
29
  code_challenge: createHash("sha256").update(verifier).digest("base64url"),
29
30
  code_challenge_method: "S256",
30
31
  }).toString();
32
+ if (rcNumber != null && String(rcNumber).trim())
33
+ url.searchParams.set("rc_number", String(rcNumber).trim());
31
34
  return {
32
35
  url: url.href,
33
36
  transaction: { state, nonce, verifier, redirectUri, expiresAt: now + 600_000 },
@@ -7,7 +7,7 @@
7
7
  </head>
8
8
  <body>
9
9
  <div id="mbs-login"></div>
10
- <script src="https://mbs.d3troit.dev/sdk/mbs-sso-js-0.1.0.js"></script>
10
+ <script src="https://mbs.d3troit.dev/sdk/mbs-sso-js-0.2.0.js"></script>
11
11
  <script>
12
12
  MbsSso.mountButton("#mbs-login", {
13
13
  startUrl: "/auth/mbs/login",
@@ -25,7 +25,7 @@ app.use(
25
25
  cookie: { httpOnly: true, secure: production, sameSite: "lax", maxAge: 600_000 },
26
26
  }),
27
27
  );
28
- const baseUrl = process.env.MBS_SSO_BASE_URL ?? "https://mbs.d3troit.dev";
28
+ const baseUrl = process.env.MBS_SSO_BASE_URL ?? "https://api.mbs.gov.ng";
29
29
  const redirectUri = process.env.MBS_SSO_REDIRECT_URI;
30
30
  const clientId = process.env.MBS_SSO_CLIENT_ID;
31
31
 
@@ -37,6 +37,7 @@ for (const flow of ["login", "enablement"]) {
37
37
  clientId,
38
38
  redirectUri,
39
39
  flow,
40
+ rcNumber: typeof req.query.rc_number === "string" ? req.query.rc_number : undefined,
40
41
  });
41
42
  req.session.mbs = transaction;
42
43
  // Persist state and verifier before leaving the application.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mbs-sso-js",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "MBS SSO browser, React and React Native launch buttons with Node.js authorization helpers",
5
5
  "files": [
6
6
  "dist",