# Verify QR Code

Verify process starts from the user scanning a QR code that is specific to your application. This section explains the different types of QR codes supported, the URL formats, as well as how they can be generated.

## 1. Choosing type of QR code

Verify supports 2 types of QR code: *"static"* and *"dynamic"*.

### **1.1 Static QR**

Static QR codes are normally used for time-bound/one-off events. They can be printed on paper and distributed, and scanned multiple times. Being static in nature, the QR codes will not work after the stipulated validity.

### **1.2 Dynamic QR**

Dynamic QR codes are normally used on digital devices such as tablet or kiosk. The QR codes should not be printed out, and should be displayed on the digital devices. Characteristics of dynamic QR codes are:

* generated on the fly
* short-lived e.g. valid for only 5 minutes after generation
* one-time used i.e. invalidated once scanned.

You can choose to generate either QR codes depending on your application needs.

***

## 2. Generate Verify QR Code

### **2.1 URL format**

The following is the format of the URL that will be used to produce Verify Dynamic QR code:

```http
https://app.singpass.gov.sg/sgverify?callback=https%3A%2F%2Ftest.yourcallbackurl%2Fcallback&client_id=STG2-SGVERIFY-SELF-TEST&nonce=4110833&qr_type=dynamic&signature_method=RS256&state=kiosk001&timestamp_expiry=1602324610000&timestamp_start=1570702210000&v=2&signature=h8jdRRpS5ArE0pdWDXHv04JiELnEvR54ulO7O0x//mewoZDQW+cfnSPdwC2kZZzLkMYtd2HjeTLBqTG5HKjbDiH3C5YkB9lS81mVgV3oj6E7LjzPZQgypNHzp1F3sBrj/4MNjJbL119VA15RJ0HlR1sOeF05yR7rFkDAZfRth37UFAFYoVDFzU4MwLYZt7W0eNRESXWVWLK94qqJg/ubR/xNKXqI93Tdw032DxapCIM3jLwQhk327f6a21ZpnSOKWXxWl1FUv4WcOxHXLvs8B/C43kJpn8TpGMHUyk5cRB/kFxljltH1Yq4n5ROhXFhjQUmk+nTMVsg31MKl6NKQnA==
```

The URL contains parameters that denotes the type of QR, validity, application ID etc, summarised in the table below. Ensure that the parameters are given in the sequence shown below:

| PARAMETER                                         | DESCRIPTION                                                                                                                                                                                                                                                                               |
| ------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| <p>callback<br><code>required</code></p>          | <p>string<br><em>Example: "https%3A%2F%2Ftest.yourcallbackurl%2Fcallback"</em><br><br>Your application's registered callback URL (URL encoded) for Verify to return authorisation code to.</p>                                                                                            |
| <p>client\_id<br><code>required</code></p>        | <p>string<br><em>Example: "STG2-SGVERIFY-SELF-TEST"</em><br><br>Unique ID for your application.</p>                                                                                                                                                                                       |
| nonce                                             | <p>string<br><em>Example: 4110833</em><br><br>Unique-random text to prevent replay attack.<br><br>Note: Mandatory only if qr\_type is dynamic</p>                                                                                                                                         |
| <p>qr\_type<br><code>required</code></p>          | <p>string<br><em>Enum: "static" "dynamic"</em><br><br>Type of QR</p>                                                                                                                                                                                                                      |
| <p>signature\_method<br><code>required</code></p> | <p>string<br><em>Default: "RS256"</em><br><br>Signature algorithm used to produce the digital signature.</p>                                                                                                                                                                              |
| <p>state<br><code>required</code></p>             | <p>string<br><em>Example: "kiosk001"</em><br><br>Identifier that represents the user's session/transaction with the client for reconciling query and response. The same value will be sent back via the callback URL. Use a unique system generated number for each user/transaction.</p> |
| <p>timestamp\_expiry<br><code>required</code></p> | <p>string<br><em>Example: "1602324610000"</em><br><br>QR code expiry timestamp (UNIX epoch time in milliseconds)</p>                                                                                                                                                                      |
| <p>timestamp\_start<br><code>required</code></p>  | <p>string<br><em>Example: "1570702210000"</em><br><br>QR code start timestamp (UNIX epoch time in milliseconds)</p>                                                                                                                                                                       |
| <p>v<br><code>required</code></p>                 | <p>string<br><em>Default: 2</em><br><br>Version of Verify API.</p>                                                                                                                                                                                                                        |
| <p>signature<br><code>required</code></p>         | <p>string<br><em>Example: "MEyCBY/XSBBB..."</em><br><br>Binary of the generated signature encoded in Base64 URL-safe format. This digital signature will be used to ensure non-repudiation of the request.</p>                                                                            |

### **2.2 Construct URL**

The process of constructing the URL consists of three steps:

#### Step 1: Form the Verify URL with the query parameters

Form the base URL, excluding the digital signature.

```
// function to derive Verify url with the query parameters 
function formURL(qrType, callbackURL, clientId, state, nonce, signatureMethod, timestampExpiry, timestampStart, version) {
 
    let nonceString = nonce ? "&nonce=" + nonce : '';
    let baseUrl = "https://app.singpass.gov.sg/sgverify";
    let sgverifyURl = baseUrl +
        "?callback=" + encodeURIComponent(callbackURL) +
        "&client_id=" + clientId +
        nonceString +
        "&qr_type=" + qrType +
        "&signature_method=" + signatureMethod +
        "&state=" + state +
        "&timestamp_expiry=" + timestampExpiry + // Saturday, 10 October 2020 10:10:10
        "&timestamp_start=" + timestampStart + // Thursday, 10 October 2019 10:10:10
        "&v=" + version;
 
    /* Display all the params */
    console.log('--- Verify URL Params ---:'.green);
    console.log(' - baseUrl: ' + baseUrl);
    console.log(' - callback: ' + callbackURL);
    console.log(' (1) callback(URL Encoded): ' + encodeURIComponent(callbackURL));
    console.log(' (2) client_id: ' + clientId);
    console.log(' (3) nonce: ' + nonce);
    console.log(' (4) qr_type: ' + qrType);
    console.log(' (5) signature_method: ' + signatureMethod);
    console.log(' (6) state: ' + state);
    console.log(' (7) timestamp_expiry: ' + timestampExpiry);
    console.log(' (8) timestamp_start: ' + timestampStart);
    console.log(' (9) v: ' + version);
 
    /* Display the URL */
    console.log('--- Verify URL ---:'.green);
    console.log(sgverifyURl);
 
    return sgverifyURl;
 
}

```

#### Step 2: Sign the Verify URL on Step(1) with your private key

Digitally sign the URL constructed in Step 1 using your application's private key with cryptographic algorithm e.g. "RSA-SHA256".

```
function signURL(sgverifyURl, keytoSign) {
    var signedSgVerifyURl = crypto.createSign('RSA-SHA256')
        .update(sgverifyURl)
        .sign(keytoSign, 'base64');
 
    /* Signature */
    console.log('--- Signature of Verify URL ---:'.green);
    console.log(signedSgVerifyURl);
 
    return signedSgVerifyURl;
}
```

#### Step 3: Add the signature into the URL

Append the digital signature as a parameter to the URL constructed in Step 1.

```
function assemblingUrlWithSignature(sgverifyURl, signedSgVerifyURl) {
 
    var sgverifyURlwithSignature = sgverifyURl +
        "&signature=" + signedSgVerifyURl;
    return sgverifyURlwithSignature;
}
```

The final URL will look like the one above, echoed below:

```http
https://app.singpass.gov.sg/sgverify?callback=https%3A%2F%2Ftest.yourcallbackurl%2Fcallback&client_id=STG2-SGVERIFY-SELF-TEST&nonce=4110833&qr_type=dynamic&signature_method=RS256&state=kiosk001&timestamp_expiry=1602324610000&timestamp_start=1570702210000&v=2&signature=h8jdRRpS5ArE0pdWDXHv04JiELnEvR54ulO7O0x//mewoZDQW+cfnSPdwC2kZZzLkMYtd2HjeTLBqTG5HKjbDiH3C5YkB9lS81mVgV3oj6E7LjzPZQgypNHzp1F3sBrj/4MNjJbL119VA15RJ0HlR1sOeF05yR7rFkDAZfRth37UFAFYoVDFzU4MwLYZt7W0eNRESXWVWLK94qqJg/ubR/xNKXqI93Tdw032DxapCIM3jLwQhk327f6a21ZpnSOKWXxWl1FUv4WcOxHXLvs8B/C43kJpn8TpGMHUyk5cRB/kFxljltH1Yq4n5ROhXFhjQUmk+nTMVsg31MKl6NKQnA==
```

### **2.3 Generate QR Code**

Once you have the URL, you can use online tools to generate static QR codes, for example:

* <https://www.qr-code-generator.com/>
* <https://www.qrcode-monkey.com/>

For dynamic QR codes, you will need to use platform specific libraries to generate the QR code image on the fly.

***

## 3. Displaying Verify QR code

Please ensure that the QR codes generated is in-line with our [display guideline.](/docs/legacy-verify/brand-guidelines-and-resources.md)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.developer.singpass.gov.sg/docs/legacy-verify/tutorial/verify-qr-code.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
