Skip to content

Commit 9f9591c

Browse files
feat: add examples for JWT embeds
1 parent db37c08 commit 9f9591c

File tree

11 files changed

+427
-68
lines changed

11 files changed

+427
-68
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
node_modules/

go/go.mod

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module embed-signing-packages/go
2+
3+
go 1.22.5
4+
5+
require github.com/golang-jwt/jwt/v5 v5.2.2 // indirect

go/go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8=
2+
github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=

go/signing.go

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import (
99
"math/rand"
1010
"strings"
1111
"time"
12+
13+
"github.com/golang-jwt/jwt/v5"
1214
)
1315

1416
// Replace with your own values
@@ -18,6 +20,29 @@ const (
1820
embedSecret = "your secret here"
1921
)
2022

23+
func generateJWTEmbedURl() string {
24+
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
25+
"sub": "xyz@xyz.com",
26+
"jti": fmt.Sprintf("%x", rand.Int63()),
27+
"iat": time.Now().Unix(),
28+
"exp": time.Now().Add(time.Hour * 1).Unix(),
29+
"iss": clientID,
30+
"ver": "1.1",
31+
"aud": "sigmacomputing",
32+
"teams": [...]string{"EmbedTeam"},
33+
"account_type": "Pro",
34+
})
35+
36+
tokenString, err := token.SignedString([]byte(embedSecret))
37+
38+
if err != nil {
39+
panic(err)
40+
}
41+
42+
url := fmt.Sprintf("https://app.sigmacomputing.com/<your org>/<your workbook>?:embed=true&:jwt=%s", tokenString)
43+
return url
44+
}
45+
2146
func myQuote(val string) string {
2247
val = strings.ReplaceAll(val, " ", "%20")
2348
return val
@@ -31,7 +56,7 @@ func urlencode(pairs map[string]interface{}) string {
3156
return strings.Join(encodedParams, "&")
3257
}
3358

34-
func main() {
59+
func secureEmbedUrl() string {
3560
params := map[string]interface{}{
3661
":nonce": fmt.Sprintf("%x", rand.Int63()),
3762
":email": "xyz@xyz.com",
@@ -54,5 +79,14 @@ func main() {
5479

5580
urlWithSignature := urlWithParams + "&" + urlencode(map[string]interface{}{":signature": signature})
5681

57-
fmt.Println(urlWithSignature)
82+
return urlWithSignature
83+
}
84+
85+
func main() {
86+
fmt.Println("=========JWT Embed URL=========")
87+
fmt.Println(generateJWTEmbedURl())
88+
fmt.Println("==================================")
89+
fmt.Println("=========Secure Embed URL=========")
90+
fmt.Println(secureEmbedUrl())
91+
fmt.Println("==================================")
5892
}

node/package-lock.json

Lines changed: 154 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

node/package.json

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{
2+
"name": "embed-signing-package",
3+
"version": "1.0.0",
4+
"description": "Example functions to sign Sigma embed urls ",
5+
"main": "signing.js",
6+
"scripts": {
7+
"start": "node signing.js"
8+
},
9+
"repository": {
10+
"type": "git",
11+
"url": "git+https://github.com/sigmacomputing/embed-signing-packages.git#main"
12+
},
13+
"keywords": [
14+
"Sigma",
15+
"Embed",
16+
"Secure",
17+
"Embeds"
18+
],
19+
"author": "",
20+
"license": "ISC",
21+
"bugs": {
22+
"url": "https://github.com/sigmacomputing/embed-signing-packages/issues"
23+
},
24+
"homepage": "https://github.com/sigmacomputing/embed-signing-packages/tree/main#readme",
25+
"dependencies": {
26+
"jsonwebtoken": "^9.0.2"
27+
}
28+
}

node/signing.js

Lines changed: 65 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
const crypto = require('crypto');
2-
const { URLSearchParams } = require('url');
1+
const crypto = require("crypto");
2+
const { URLSearchParams } = require("url");
3+
const jwt = require("jsonwebtoken");
34

45
// Replace with your own values
5-
const EMBED_PATH = "your path here"
6-
const CLIENT_ID = "your clientid here"
7-
const EMBED_SECRET = "your secret here"
6+
const EMBED_PATH = "your path here";
7+
const CLIENT_ID = "your clientid here";
8+
const EMBED_SECRET = "your secret here";
89

910
function urlencode(pairs) {
1011
const params = new URLSearchParams();
@@ -14,25 +15,66 @@ function urlencode(pairs) {
1415
return params.toString();
1516
}
1617

17-
const params = {
18-
":nonce": crypto.randomBytes(16).toString('hex'),
19-
":email": "xyz@xyz.com",
20-
":external_user_id": "xyz@xyz.com",
21-
":client_id": CLIENT_ID,
22-
":time": Math.floor(new Date().getTime() / 1000),
23-
":session_length": 3600,
24-
":mode": "view",
25-
":external_user_team": "EmbedTeam",
26-
// custom controls/parameters
27-
// "Store-Region": "West",
28-
};
18+
function generateSignedEmbedUrl() {
19+
const params = {
20+
":nonce": crypto.randomBytes(16).toString("hex"),
21+
":email": "xyz@xyz.com",
22+
":external_user_id": "xyz@xyz.com",
23+
":client_id": CLIENT_ID,
24+
":time": Math.floor(new Date().getTime() / 1000),
25+
":session_length": 3600,
26+
":mode": "view",
27+
":external_user_team": "EmbedTeam",
28+
// custom controls/parameters
29+
// "Store-Region": "West",
30+
};
2931

30-
const urlWithParams = `${EMBED_PATH}?${urlencode(params)}`;
32+
const urlWithParams = `${EMBED_PATH}?${urlencode(params)}`;
3133

32-
const signature = crypto.createHmac('sha256', Buffer.from(EMBED_SECRET, 'utf8'))
33-
.update(Buffer.from(urlWithParams, 'utf8'))
34-
.digest('hex');
34+
const signature = crypto
35+
.createHmac("sha256", Buffer.from(EMBED_SECRET, "utf8"))
36+
.update(Buffer.from(urlWithParams, "utf8"))
37+
.digest("hex");
3538

36-
const urlWithSignature = `${urlWithParams}&:signature=${signature}`;
39+
const urlWithSignature = `${urlWithParams}&:signature=${signature}`;
40+
return urlWithSignature;
41+
}
42+
43+
function generateJwtEmbedUrl() {
44+
const payload = {
45+
iss: CLIENT_ID,
46+
sub: "xyz@xyz.com",
47+
aud: "sigmacomputing",
48+
jti: crypto.randomBytes(16).toString("hex"),
49+
ver: "1.1",
50+
iat: Math.floor(new Date().getTime() / 1000),
51+
exp: Math.floor(new Date().getTime() / 1000) + 3600,
52+
teams: ["EmbedTeam"],
53+
account_type: "Pro",
54+
};
55+
56+
const token = jwt.sign(payload, EMBED_SECRET, {
57+
algorithm: "HS256",
58+
keyid: CLIENT_ID,
59+
});
60+
const urlWithToken = `https://app.sigmacomputing.com/<your org>/<your workbook>?:embed=true&:jwt=${token}`;
61+
return urlWithToken;
62+
}
63+
64+
function main() {
65+
const jwtUrl = generateJwtEmbedUrl();
66+
console.log(
67+
`===========JWT Embed URL============
68+
${jwtUrl}
69+
==========================================`
70+
);
71+
72+
const urlWithSignature = generateSignedEmbedUrl();
73+
console.log(
74+
`===========Signed Embed URL============
75+
${urlWithSignature}
76+
==========================================`
77+
);
78+
}
3779

38-
console.log(urlWithSignature);
80+
main();

0 commit comments

Comments
 (0)