Implement user sign up
Signup is the first step in a user’s journey with your application. For B2B applications, each user may be associated with an organization. A user can belong to one or more organizations.
Here are some common signup use cases:
- New user and organization: The first user to sign up creates a new organization and becomes its administrator.
- Joining an existing organization: An existing user can join another organization or workspace within your application.
- Invitation-based signup: A new user signs up by accepting an email invitation and is automatically added to the inviting organization.
- Automatic organization joining: A user with a corporate email (e.g.,
jane.doe@acme.com
) signs up and is prompted to join the existing “ACME Inc.” organization. - User provisioning via identity provider: A user account is created programmatically through an enterprise identity provider (e.g., Okta, Azure AD). The user first logs in via SSO instead of a traditional signup.
Scalekit helps you implement all such signup flows while handling the complexity of user management and authentication.
Sign up with Scalekit’s hosted signup page
Section titled “Sign up with Scalekit’s hosted signup page”You can direct users to Scalekit’s managed signup page by adding the prompt: 'create'
parameter when generating the authorization URL. This is the simplest way to implement a signup flow.
-
Install the Scalekit SDK
Section titled “Install the Scalekit SDK”npm install @scalekit-sdk/nodepip install scalekit-sdk-pythongo get -u github.com/scalekit-inc/scalekit-sdk-go/* Gradle users - add the following to your dependencies in build file */implementation "com.scalekit:scalekit-sdk-java:1.1.3"<!-- Maven users - add the following to your `pom.xml` --><dependency><groupId>com.scalekit</groupId><artifactId>scalekit-sdk-java</artifactId><version>1.1.3</version></dependency>Copy your API credentials from the Scalekit dashboard’s API Config section and set them as environment variables.
Terminal window SCALEKIT_ENVIRONMENT_URL='<YOUR_ENVIRONMENT_URL>'SCALEKIT_CLIENT_ID='<ENVIRONMENT_CLIENT_ID>'SCALEKIT_CLIENT_SECRET='<ENVIRONMENT_CLIENT_SECRET>'Create a new Scalekit client instance after initializing the environment variables.
utils/auth.js import { Scalekit } from '@scalekit-sdk/node';export let scalekit = new Scalekit(process.env.SCALEKIT_ENVIRONMENT_URL,process.env.SCALEKIT_CLIENT_ID,process.env.SCALEKIT_CLIENT_SECRET);utils/auth.py from scalekit import ScalekitClient, AuthorizationUrlOptions, CodeAuthenticationOptionsimport osscalekit = ScalekitClient(os.environ.get('SCALEKIT_ENVIRONMENT_URL'),os.environ.get('SCALEKIT_CLIENT_ID'),os.environ.get('SCALEKIT_CLIENT_SECRET'))utils/auth.go package mainimport ("os""github.com/scalekit-inc/scalekit-sdk-go")var scalekit, err = scalekit.NewScalekitClient(os.Getenv("SCALEKIT_ENVIRONMENT_URL"),os.Getenv("SCALEKIT_CLIENT_ID"),os.Getenv("SCALEKIT_CLIENT_SECRET"),)if err != nil {panic(err)}utils/Auth.java import com.scalekit.ScalekitClient;import com.scalekit.Environment;public class Auth {public static ScalekitClient scalekit;static {Environment.configure(System.getenv("SCALEKIT_ENVIRONMENT_URL"),System.getenv("SCALEKIT_CLIENT_ID"),System.getenv("SCALEKIT_CLIENT_SECRET"));scalekit = new ScalekitClient(System.getenv("SCALEKIT_ENVIRONMENT_URL"),System.getenv("SCALEKIT_CLIENT_ID"),System.getenv("SCALEKIT_CLIENT_SECRET"));}} -
Redirect the user to the sign up page
Section titled “Redirect the user to the sign up page”Generate the authorization URL by passing a registered callback URL and scopes to the Scalekit SDK.
Express.js const redirectUri = 'http://localhost:3000/api/callback';const options = {scopes: ['openid', 'profile', 'email', 'offline_access'],prompt: 'create', // explicitly takes you to sign up flow};const authorizationUrl = scalekit.getAuthorizationUrl(redirectUri, options);res.redirect(authorizationUrl);Flask from scalekit import AuthorizationUrlOptionsredirect_uri = 'http://localhost:3000/api/callback'options = AuthorizationUrlOptions()options.scopes=['openid', 'profile', 'email', 'offline_access']options.prompt='create' # optional: explicitly takes you to sign up flowauthorization_url = scalekit.get_authorization_url(redirect_uri, options)# For web frameworks like Flask/Django:# return redirect(authorization_url)Gin redirectUri := "http://localhost:3000/api/callback"options := scalekit.AuthorizationUrlOptions{Scopes: []string{"openid", "profile", "email", "offline_access"},Prompt: "create", // explicitly takes you to sign up flow}authorizationUrl, err := scalekit.GetAuthorizationUrl(redirectUri, options)if err != nil {// handle error appropriatelypanic(err)}// For web frameworks like Gin:// c.Redirect(http.StatusFound, authorizationUrl.String())Spring import com.scalekit.internal.http.AuthorizationUrlOptions;import java.net.URL;import java.util.Arrays;String redirectUri = "http://localhost:3000/api/callback";AuthorizationUrlOptions options = new AuthorizationUrlOptions();options.setScopes(Arrays.asList("openid", "profile", "email", "offline_access"));options.setPrompt("create");URL authorizationUrl = scalekit.authentication().getAuthorizationUrl(redirectUri, options);This will redirect the user to Scalekit’s managed sign-in page.
-
Allow users to sign up
Section titled “Allow users to sign up”Users can now sign in or sign up using their preferred authentication methods. Each authentication method is managed by Scalekit to successfully verify the user’s identity.
Configure authentication methods Enable passwordless, social, or enterprise SSO to customize the signup experience. -
Retrieve user profile after identity verification
Section titled “Retrieve user profile after identity verification”Scalekit triggers a callback to your registered callback URL with an authorization code. Exchange the code to get the user’s profile information.
import scalekit from '@/utils/auth.js'const redirectUri = 'http://localhost:3000/api/callback';// Get the authorization code from the scalekit initiated callbackapp.get('/api/callback', async (req, res) => {const { code, error, error_description } = req.query;if (error) {return res.status(401).json({ error, error_description });}try {// Exchange the authorization code for a user profileconst authResult = await scalekit.authenticateWithCode(code, redirectUri);const { user } = authResult;// "user" object contains the user's profile information// Next step: Create a session and log in the user5 collapsed linesres.redirect('/dashboard/profile');} catch (err) {console.error('Error exchanging code:', err);res.status(500).json({ error: 'Failed to authenticate user' });}});6 collapsed linesfrom flask import Flask, request, redirect, jsonifyfrom scalekit import ScalekitClient, CodeAuthenticationOptionsapp = Flask(__name__)# scalekit imported from your auth utilsredirect_uri = 'http://localhost:3000/api/callback'@app.route('/api/callback')def callback():code = request.args.get('code')error = request.args.get('error')error_description = request.args.get('error_description')if error:return jsonify({'error': error, 'error_description': error_description}), 401try:# Exchange the authorization code for a user profileoptions = CodeAuthenticationOptions()auth_result = scalekit.authenticate_with_code(code, redirect_uri, options)user = auth_result.user# "user" object contains the user's profile information# Next step: Create a session and log in the user4 collapsed linesreturn redirect('/dashboard/profile')except Exception as err:print(f'Error exchanging code: {err}')return jsonify({'error': 'Failed to authenticate user'}), 5009 collapsed linespackage mainimport ("log""net/http""os""github.com/gin-gonic/gin""github.com/scalekit-inc/scalekit-sdk-go")// Create Scalekit client instancevar scalekitClient = scalekit.NewScalekitClient(os.Getenv("SCALEKIT_ENVIRONMENT_URL"),os.Getenv("SCALEKIT_CLIENT_ID"),os.Getenv("SCALEKIT_CLIENT_SECRET"),)const redirectUri = "http://localhost:3000/api/callback"func callbackHandler(c *gin.Context) {code := c.Query("code")errorParam := c.Query("error")errorDescription := c.Query("error_description")if errorParam != "" {c.JSON(http.StatusUnauthorized, gin.H{"error": errorParam,"error_description": errorDescription,})return}// Exchange the authorization code for a user profileoptions := scalekit.AuthenticationOptions{}authResult, err := scalekitClient.AuthenticateWithCode(code, redirectUri, options,)if err != nil {log.Printf("Error exchanging code: %v", err)c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to authenticate user",})return}user := authResult.User// "user" object contains the user's profile information// Next step: Create a session and log in the userc.Redirect(http.StatusFound, "/dashboard/profile")}10 collapsed linesimport com.scalekit.ScalekitClient;import com.scalekit.internal.http.AuthenticationOptions;import com.scalekit.internal.http.AuthenticationResponse;import org.springframework.web.bind.annotation.*;import org.springframework.web.servlet.view.RedirectView;import org.springframework.http.ResponseEntity;import org.springframework.http.HttpStatus;import java.util.HashMap;import java.util.Map;@RestControllerpublic class CallbackController {private final String redirectUri = "http://localhost:3000/api/callback";@GetMapping("/api/callback")public Object callback(@RequestParam(required = false) String code,@RequestParam(required = false) String error,@RequestParam(name = "error_description", required = false) String errorDescription) {if (error != null) {Map<String, String> errorResponse = new HashMap<>();errorResponse.put("error", error);errorResponse.put("error_description", errorDescription);return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(errorResponse);}try {// Exchange the authorization code for a user profileAuthenticationOptions options = new AuthenticationOptions();AuthenticationResponse authResult = scalekit.authentication().authenticateWithCode(code, redirectUri, options);var user = authResult.getUser();// "user" object contains the user's profile information// Next step: Create a session and log in the userreturn new RedirectView("/dashboard/profile");8 collapsed lines} catch (Exception err) {System.err.println("Error exchanging code: " + err.getMessage());Map<String, String> errorResponse = new HashMap<>();errorResponse.put("error", "Failed to authenticate user");return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(errorResponse);}}}The
authenticateWithCode
method returns an object containing the user’s profile information (user
object) andidToken
(JWT).{user: {email: "john.doe@example.com",emailVerified: true,givenName: "John",name: "John Doe",id: "usr_74599896446906854"},idToken: "eyJhbGciO..",accessToken: "eyJhbGciOi..",refreshToken: "rt_8f7d6e5c4b3a2d1e0f9g8h7i6j..",expiresIn: 299}{"at_hash": "ec_jU2ZKpFelCKLTRWiRsg","aud": ["skc_58327482062864390"],"azp": "skc_58327482062864390","c_hash": "6wMreK9kWQQY6O5R0CiiYg","client_id": "skc_58327482062864390","email": "john.doe@example.com","email_verified": true,"exp": 1742975822,"family_name": "Doe","given_name": "John","iat": 1742974022,"iss": "https://scalekit-z44iroqaaada-dev.scalekit.cloud","name": "John Doe","oid": "org_59615193906282635","sid": "ses_65274187031249433","sub": "usr_63261014140912135"}You can decode the
idToken
to access user information like email, name, and profile verification status directly from the token claims.
After the user signs up, they are redirected back to your application, and you can proceed to create a session.