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 🙏

© 2024 – Pkg Stats / Ryan Hefner

@beedgtl/mobile-id

v1.0.0

Published

Mobile ID Web SDK for B2B clients. This SDK allows to use authentication with a Mobile ID in DI mode.

Downloads

11

Readme

npm license npm version install size npm downloads

Beeline Mobile ID Web SDK is a javascript package that allows web developers to easily integrate their web applications with the Mobile ID service. This module will allow you to add the authentication and enable the end user's personal data autofill functionality in your website.

Concept

General service interaction scenario:

  1. The User enters your website and chooses authorization over Mobile ID.
  2. The user is redirected to the Operator's page.
  3. The Operator sends a PUSH message to the user's device with a request to confirm authentication on your resource. If the User's device cannot receive a PUSH, an SMS-message will be sent, containing an authentication confirmation link.
  4. The user clicks "Accept" or "OK" (depending on the carrier) on the mobile phone.
  5. The user is redirected to your redirect_uri and request completion of the authentication process is sent.
  6. If user authentication was successful and "Form auto-completion" is provided by your price plan, a request for the user's personal data is sent by the SDK and fulfilled by the Operator.

Contact Us

Do you need help? Contact Support: [email protected]

Browser Support

Browsers supporting the ECMAScript 2015 (ES6) standard

| Chrome | Safari | Firefox | Opera | Samsung Internet | Edge | IE | |----------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------|:--------------------------------------------------------------------------------------------------------------------------:| | Latest ✔ | Latest ✔ | Latest ✔ | Latest ✔ | Latest ✔ | Latest ✔ | 11 ✗ Not supported |

Get Started

Registration

To start working with the service, you need to:

  1. Go through the registration process on the website https://mobileid.beeline.ru. You can register through your Personal Account, or fill out a questionnaire together with our manager:

    a. Decide on the connection method
    b. Choose a tariff:

    • Sign In only
    • Autofill / base
    • Autofill / base and address
    • Autofill / full

    c. Provide server-side implementation for a scheme with operator screens — HTTPS Redirect URL and HTTPS JWKS URL (for request personal data).

  2. Create an entry for a digital resource. As a result, you will get client_id and client_secret, client_name values (field of the form – Application Name), that will be attached to request from the Mobile ID platform to the operator that serves the subscriber's phone number.

Installation

Install a stable version via Yarn or npm:

yarn add @beedgtl/mobile-id
# or
npm i @beedgtl/mobile-id

Usage

// add the module to your code
import { MobileIDClient } from '@beedgtl/mobile-id';

Initialize client with appropriate configuration:

const mobileIDClient = new MobileIDClient({
    credentials: {
        id: 'your_client_id',
        name: 'your_client_name',
        key: 'your_encoded_access_key',
    },
    redirectUrl: 'https://your-app.domain.ru/',
    scope: ['mc_authn'],
    acrValues: 3,
    onError: (error) => { /* Body of the error handler function */ },
    onSuccess: (tokenInfo, premiumInfo) => { /* Body of the success result handler function */ },
});

Next, create button component and insert it in your DOM:

import { Text } from '@beedgtl/mobile-id';

const button = mobileIDClient.createButton('violet', 'xl', { text: Text.PRIMARY });
document.querySelector('#root').appendChild(button);

Important

⚠️ If redirectUrl - your website redirect url, specified (as redirect_uri) during service provider account registration - doesn't match your login page url, you need to initialize MobileIDClient again. ❗The SDK configuration must be identical in both calls

First, initialize MobileIDClient on the login page.

configuration.js
export const MOBID_CONF = {
    credentials: {
        id: 'your_client_id',
        name: 'your_client_name',
        key: 'your_encoded_access_key',
    },
    redirectUrl: 'https://your-app.domain.ru/root/profile',
    scope: ['mc_authn'],
    acrValues: 3,
    premium: true,
    onError: () => { /* Some fn */ },
    onSuccess: () => { /* Some fn */ },    
};
login-page.js
import { MobileIDClient, Text } from '@beedgtl/mobile-id';
import { MOBID_CONF } from './configuration.js';

// Login page route 
// For example, https://your-app.domain.ru/login

const mobileIDClient = new MobileIDClient(MOBID_CONF);
const button = mobileIDClient.createButton('bright', 'm', { text: Text.DEFAULT });
document.querySelector('#root').appendChild(button);

mobileIDClient.setMsisdn(someMsisdn);

Second, initialize MobileIDClient on the redirectUrl route page

profile-page.js
import { MobileIDClient } from '@beedgtl/mobile-id';
import { MOBID_CONF } from './configuration.js';

// After login page route 
// For example, https://your-app.domain.ru/root/profile

const mobileIDClient = new MobileIDClient(MOBID_CONF);

/* No need to create button yet */
/* If authentication fails, an onError callback will be invoked */

If premium option is true and authentication process completes successfully, but personal data request fails, then onSuccess and onError callbacks will be invoked together. At that onSuccess will be invoked with only one argument MCToken and onError will be invoked with Error.method set to personalData.

Result data

An example js object tokenInfo (passed as first argument of onSuccess callback):

{
  accessToken: "eyJhbGciOiJSUzI1NiIsImtpZCI6InM0aWo5Q1pwOVJNcGpwTFFISGlRSVJLcU9MSDEyZEFFNndGL1kyRloxNlU9IiwidHlwIjoiSldUIn0.eyJzdWIiOiJjYWIxMWJmZS1hMGJiLTQzZmUtYjVhNi1mNDUyODNiNDFjMTciLCJpYXQiOjE2MzcwNjIyMTEsImV4cCI6MTYzNzA2MjgxMSwianRpIjoiODFlOGI1MjItZDkwZS00MzMwLTg3NGYtZDUxMjcwZjdlZWFhIiwiYXpwIjoidmFzLXRlc3QiLCJhdWQiOiIiLCJpc3MiOiJodHRwczovL2FnZ3Jtb2JpbGVpZC5iZWVsaW5lLnJ1IiwibmJmIjoxNjM3MDYyMjExfQ.Bse3IH5Tvgdw1QcyYvNbt4iVWIU1mxw5Qmb0gvuX43INJIIVMc_WauCyw41t4mftAsvLn6pEHqGSge6OT3BraYbK_ZO0kgGbmLmdan_FTUTHZBzEVUO3JGJHs5jk9MzZQZUQPyupj9VcXXNrw9102e6EzCpZqe9_CQ2W-RWaAgWnwVZk1pYZi-rYeDxgoZEaMPpkx7u8qal2x6fNPBW68jNjg-cvlaPsZIy-ZD3otiOi0Fpq-HM0fofEa8Z4tDDapv3FPA5ahTB7CEU9Z6iwQ5qpeJSWv0SOYFvdCuOy7PBWVc-X7EuhaM_v4wtWnudmIEsKzg-o0fsGMIsTP5XkFA",
  expiresIn: 599,
  scope: 'openid mc_identity_basic mc_authn', 
  idToken: "eyJhbGciOiJSUzI1NiIsImtpZCI6InM0aWo5Q1pwOVJNcGpwTFFISGlRSVJLcU9MSDEyZEFFNndGL1kyRloxNlU9IiwidHlwIjoiSldUIn0.eyJhdF9oYXNoIjoiZlQtX2gwcGFkWEtwSmxMVV90ckdlZyIsInN1YiI6ImNhYjExYmZlLWEwYmItNDNmZS1iNWE2LWY0NTI4M2I0MWMxNyIsImFtciI6IlNJTV9PSyIsImtpZCI6InNpZ0tleSIsImlzcyI6Imh0dHBzOi8vYWdncm1vYmlsZWlkLmJlZWxpbmUucnUiLCJhdWQiOiJ2YXMtdGVzdCIsImFjciI6MiwiYXpwIjoidmFzLXRlc3QiLCJhdXRoX3RpbWUiOjE2MzcwNjIyMTEsInJlY2lwaWVudCI6Imh0dHBzOi8vYWdncm1vYmlsZWlkLmJlZWxpbmUucnUvbm90aWZpY2F0aW9uIiwiaWF0IjoxNjM3MDYyMjExLCJleHAiOjE2MzcwNjI4MTEsImp0aSI6IjgzYjQ3Y2QyLTAwYjMtNGQxNS05MjA1LTgwODM2ZWJlZjYxNSIsIm5iZiI6MTYzNzA2MjIxMX0.UMMcw-QsEJw22VDHASJ7Vr0W4_u1jeFbTuK5auaIbW6qGaPlQI-FXJLFkM7KrDTtr1qD4CP1f9BLNy4xQ_Pzzlfqwpcq6sMfRB84kEVoVDujhDUEngbSDFvuvjsJGAJf3buWC-7I1q5_B_6XRiOHpiH-q31FDMAFsZf4uagK6432gHcA3pX947wsE42PVJYnhFB0zvM6SGryF933Jiy6b3SrNTQ9ztZEFWNzxaon4LtVDw9XyMdQR15ZJAylOJcMAHsiFEPUDJe997OfMgwFP0JgmGvjXVTix8GfsScbrngozPuDsmJv4Ee1s64iT7ca9VBkcBla4tH74R7z8q53jA",
}

An example string of premiumInfo (passed as second argument of onSuccess callback):

eyJ0eXAiOiJKV1QiLCJlbmMiOiJBMTI4R0NNIiwiYWxnIjoiUlNBLU9BRVAifQ.Wk_DFYjpCnS_87LU1pf1Fzub9_SfRGei9twHi9GYT-MZeD8daYrUW-SJkfl6idH_2lRtRsfZiiXHo8QrSJi4NyQxi_4SD4P2FncJnLKe0gyUCCboc6IEfnpdw4D8kTaw0FLv8_MdeM0Wb1NKBV4CK52mVZSNcNj7KaXBaueByzbrS5Hf98bYxiPgRmYNL84xMMlEOuIJdZYBJOICVlXBXi63LDa75PzyuJQkKxlxdNX5c5F1lm4E

Documentation

MobileIDClient constructor properties

MobileIDClient methods and callbacks

Custom types

Theme

type Theme = 'light' | 'violet' | 'bright';

| --- | light | violet | bright | |:----------:|--------------------------------------------------------------------|--------------------------------------------------------------------|--------------------------------------------------------------------| | logo | #5400ba | #fff | #333 | | text | #333 | #fff | #333 | | background | #fff | #5400ba | #ffcb00 |

Size

Differences in padding, height, logo and font sizes. The button component has a width 100%. Use a wrapper block if needed.

type Size = 's' | 'm' | 'l' | 'xl';

ButtonConfig

interface ButtonConfig {
  text?: string,
  isSubmit?: boolean,
}
  • isSubmit - when set to true, the button will be created with type="submit". Default: false (type="button")
  • text - when left empty or falsy, a simple circle-shaped button with a logo will be created. Recommend, use one of the available texts (see enum Text). If it isn't clear from context of the page, how the login will be performed, recommend add an explanatory caption under the button.

Text

export declare enum Text {
  DEFAULT = 'Войти по номеру телефона',
  PRIMARY = 'Войти с Мобильным ID',
  SECONDARY = 'Войти через Мобильный ID',
}

Credentials

interface Credentials {
  id: string, // client_id from service provider account
  key: string, // btoa(`${client_id}:${client_secret}`), client_secret from service provider account
  name: string, // client_name from service provider account
}

MCToken

interface MCToken {
  scope: string,
  idToken: string,
  expiresIn: number,
  accessToken: string,
}

Error

interface Error {
  error: string,
  errorDescription?: string,
  method: 'authentication' | 'personalData',
}

How to decrypt user's personal data

To work with encrypted data in the response from premium info, you must:

  1. Generate a pair of RSA keys (public and private) in JWK format with following parameters:
    • Key Size = 2048
    • Key Use = encryption
    • Algorithm = RSA-OAEP
  2. Place the public key on the JWKS Url
  3. Give the JWKS Url that contains JWK for encryption to the operator. There is a corresponding field in the application form for registration in the Mobile ID service
  4. Keep the private key secret and use it to decrypt the data received in the responses from premiuminfo endpoint

To generate a key, you can use the online service — https://mkjwk.org/. An example of public key:

{
  "keys": [
    {
      "kty": "RSA",
      "e": "AQAB",
      "use": "enc",
      "kid": "UCGQkw55DlgzhRp88dkdOiTVn1EUtTTYFytL7GagOAA",
      "alg": "RSA-OAEP",
      "n": "24M0ceQ2gzUENyPi8lg98V1jNv727XOc5JC1oBMWt71BcWVgzEkHnfrJQ_iPIehj1103utBcB2nZzPW7bTo3vUAFuiJTIzIlpm6LBEAB6ayF2wBP_IBUppYcuIs0M0lvDPwGbahgYez0IoiJ8aNowg8g_C2tcUYMOAjKTfs13tqUUrzj5_Xkmw8ZlSciUWuVZdopMXuxWsOOfgOlKW_gCpiodTfSvnPXvdU1Wy6enopBP1ELDOWbvp-_5eGunPEmjWDFgPMCJUnLrUikki6UIwClMLYvnTDQ4ee_kH5zqZ0l_vgGE1cedXlzgTdByH0e9nY1d5a8AQbQfEHuEFoQ"
    }
  ]
}

Public key description:

| Field | Description | |-------|----------------------------------------------------------------------------------------------------------| | kty | The encryption algorithm. To work with the service — always "RSA" | | e | The exponent of the public key in the BASE64URL encoded format. To work with the service — always "AQAB" | | use | The method of "use". For encryption — "enc" | | kid | Key id (id) | | alg | Name of the encryption algorithm | | n | Public key module in BASE64 URL encoded format |

General procedure for processing the premiumInfo response

The content of the response is a JWE token consisting of 5 components:

BASE64URL(JWE Protected Header) + '.' +
BASE64URL(JWE Encrypted Key) + '.' +
BASE64URL(JWE Initialization Vector) + '.' +
BASE64URL(JWE Ciphertext) + '.' +
BASE64URL(JWE Authentication Tag)

The definitions of the components can be found in the standard RFC 7516 (section 2).

Response body decryption

The response should be processed according to the standard RFC 7516 (section 5.2). Decryption should be performed using a private key according to the following algorithm:

  1. Extract and decode values from JWE from BASE64URL
  2. Calculate the Secret - Content Encryption Key —CEK) - decrypt the values of the JWE Encrypted Key with the Recipient's private key using the algorithm specified in the JWE Protected Header
  3. Calculate plaintext - decrypt the JWE Ciphertext by the method specified in the JWE Protected Header using the secret (CEK), initialization vector (JWE InitializationVector) and authentication Tag (JWE Authentication Tag)

Example, JAVA decryption:

import org.forgerock.json.jose.common.JwtReconstruction;
import org.forgerock.json.jose.jwe.EncryptedJwt;
import org.forgerock.json.jose.jwk.RsaJWK;

String encrypted; // premiuminfo response
String jwkValue; // a string containing JWK

RsaJWK jwk = RsaJWK.parse(jwkValue);
EncryptedJwt jwt = new JwtReconstruction().reconstructJwt(encrypted, EncryptedJwt.class);
jwt.decrypt(jwk.toRSAPrivateKey());

String result = jwt.getClaimsSet().toString();

Example, Node.js decryption:

const jose = require('node-jose');

const PID = 'premiumInfo_response_encrypted';
const privatekey = 'string containing JWK';

const decrypt = async (encData, privatekey) => {
    const keystore = jose.JWK.createKeyStore();
    
    const key = await keystore.add(privatekey, 'pem');
    const result = await jose.JWE.createDecrypt(key).decrypt(encData);
    const decriptPID = new TextDecoder().decode(result.payload);
 
    return decriptPID
};

const decryptedData = decrypt(PID, privatekey);