Single Sign-On (SSO)

What is Single Sign-On

If you have accounts of your users in your system - you can effectively provide this data using a JSON Web Token generated on your server to authenticate users on your public roadmap. This mechanism is called Single Sign-On.

How to generate a token

Here are the instructions on how to generate and use a token for signing in users automatically on your public roadmap or in your widgets

Get required parameters from your ProdCamp account

  • Login to your ProdCamp account (you must be an account administrator)
  • Go to the Settings page and then to the Workspace tab
  • On the Workspace tab, there are two important things that you will need to generate a token: Workspace Id and Secret key. You will need it a bit later in this article.

Install library

First, you need to install a specific library for working with JWT tokens
Node.js
C#
Java
PHP
Ruby
Python
Go
1
npm install --save jsonwebtoken
Copied!
1
# Read more here:
2
https://www.nuget.org/packages/System.IdentityModel.Tokens.Jwt/
Copied!
1
# Read more here:
2
https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt/0.7.0
Copied!
1
composer require firebase/php-jwt
Copied!
1
sudo gem install jwt
Copied!
1
pip install PyJWT
Copied!
1
go get github.com/dgrijalva/jwt-go
Copied!

Generate the token

Copy and insert the Secret key from the Workspace tab to the SecretKey variable in the snippet. Fill in the user data by providing user email, first name, last name, etc., and the Workspace Id. Then encode this data using the secret key like it's shown below:
Node.js
C#
Java
PHP
Ruby
Python
Go
1
var jwt = require('jsonwebtoken');
2
3
var SecretKey = 'your_secret_key';
4
5
function createToken() {
6
var userData = {
7
avatarUrl: 'user_avatar_url',
8
email: '[email protected]' // required
9
firstName: 'John',
10
lastName: 'Doe',
11
company: JSON.stringify({
12
name: 'Foo Company',
13
revenue: 1000
14
}),
15
workspace_id: '01234567-1c34-1b34-1234-cecb45ab891f' // required
16
};
17
return jwt.sign(userData, SecretKey, {algorithm: 'HS256'});
18
}
19
20
var token = createToken();
Copied!
1
private static string SecretKey = "your_secret_key";
2
3
public static string CreateToken()
4
{
5
var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(SecretKey));
6
var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256Signature);
7
var tokenHandler = new JwtSecurityTokenHandler();
8
const header = new JwtHeader(credentials);
9
10
var tokenDescriptor = new SecurityTokenDescriptor
11
{
12
Subject = new ClaimsIdentity(
13
new List<Claim>() {
14
new Claim("email", "[email protected]"), // required
15
new Claim("avatarUrl", "user_avatar_url"),
16
new Claim("firstName", "John"),
17
new Claim("lastName", "Doe"),
18
new Claim("company",
19
// Newtonsoft.Json library usage
20
JsonConvert.SerializeObject(new {
21
Name = "Foo Company",
22
Revenue = 1000
23
})
24
),
25
new Claim("workspace_id", "01234567-1c34-1b34-1234-cecb45ab891f") // required
26
}
27
),
28
SigningCredentials = creds
29
};
30
31
var token = tokenHandler.CreateToken(tokenDescriptor);
32
return tokenHandler.WriteToken(token);
33
}
Copied!
1
import java.util.HashMap;
2
3
import io.jsonwebtoken.Jwts;
4
import io.jsonwebtoken.SignatureAlgorithm;
5
6
public class TokenFactory {
7
private static final String SecretKey = "your_secret_key";
8
9
public static String createToken() throws Exception {
10
HashMap<String, Object> userData = new HashMap<String, Object>();
11
12
// new CompanyDTO(companyName, revenue)
13
CompanyDTO companyDto = new CompanyDTO("Foo Company", 1000);
14
Gson gson = new Gson();
15
String companyJson = gson.toJson(companyDto);
16
17
userData.put("email", "[email protected]");
18
userData.put("avatarUrl", "user_avatar_url");
19
userData.put("firstName", "John");
20
userData.put("lastName", "Doe");
21
userData.put("company", companyJson);
22
userData.put("workspace_id", "01234567-1c34-1b34-1234-cecb45ab891f"); // required
23
24
return Jwts.builder()
25
.setClaims(userData)
26
.signWith(SignatureAlgorithm.HS256, SecretKey.getBytes("UTF-8"))
27
.compact();
28
}
29
}
Copied!
1
use \Firebase\JWT\JWT;
2
3
$SecretKey = 'your_secret_key';
4
5
function createToken() {
6
$companyData = [
7
'name' => 'Foo Company',
8
'revenue' => 1000
9
];
10
11
$companyDataJson = json_encode($companyData);
12
13
$userData = [
14
'email' => '[email protected]', // required
15
'avatarUrl' => 'user_avatar_url',
16
'firstName => 'John',
17
'lastName' => 'Doe',
18
'company' => $companyDataJson
19
'workspace_id' => '01234567-1c34-1b34-1234-cecb45ab891f' // required
20
];
21
return JWT::encode($userData, $SecretKey, 'HS256');
22
}
Copied!
1
require 'jwt'
2
require 'json'
3
4
SecretKey = 'your_secret_key'
5
6
def createToken()
7
companyData = {
8
name: 'Foo Company',
9
revenue: 1000
10
}
11
12
userData = {
13
email: '[email protected]' # required
14
avatarUrl: 'user_avatar_url',
15
firstName: 'John',
16
lastName: 'Doe',
17
company: companyData.to_json,
18
workspace_id: '01234567-1c34-1b34-1234-cecb45ab891f' # required
19
}
20
21
JWT.encode(userData, SecretKey, 'HS256')
22
end
Copied!
1
import jwt
2
import json
3
4
secret_key = 'your_secret_key'
5
6
def create_token():
7
company_data = {
8
'name': 'Foo Company',
9
'revenue': 1000
10
}
11
12
company_json = json.dumps(company_data)
13
14
user_data = {
15
'avatarUrl': 'user_avatar_url',
16
'email': '[email protected]' # required
17
'firstName': 'John',
18
'lastName': 'Doe',
19
'company': company_json
20
'workspace_id': '01234567-1c34-1b34-1234-cecb45ab891f' # required
21
}
22
23
return jwt.encode(user_data, secret_key, algorithm='HS256')
Copied!
1
import (
2
"github.com/dgrijalva/jwt-go"
3
"encoding/json"
4
)
5
6
const SecretKey = "your_secret_key"
7
8
type CompanyData struct {
9
Name string
10
Revenue int
11
}
12
13
func createToken() (string, error) {
14
companyData = CompanyData {
15
Name: "Foo Company",
16
Revenue: 1000
17
}
18
19
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
20
"avatarUrl": "user_avatar_url",
21
"email": "[email protected]" // required
22
"firstName": "John",
23
"lastName": "Doe",
24
"company": json.Marshal(companyData),
25
"workspace_id": '01234567-1c34-1b34-1234-cecb45ab891f' // required
26
})
27
return token.SignedString([]byte(SecretKey))
28
}
Copied!

How to use the token to authenticate public roadmap users

After that, you can use the generated token inside the query parameter of a public roadmap URL like https://roadmap.prodcamp.com?token={generated_token} and provide this link somewhere inside your app to quickly redirect your users to your public roadmap page where they will be automatically authenticated and will have the ability to leave feedback right away.
You can also use this token to secure your widgets from unauthorized access. Learn more here.
Last modified 2mo ago