SDK Authentication

Authentication Method

The Open Ledger React SDK uses access tokens for authentication:

  • Access token - Using an entity-scoped token obtained from the /v1/entities/auth/generate-token endpoint

Setting Up Authentication

The recommended approach is to use an access token for authentication:

1import { OpenLedgerProvider } from "@openledger/accounting-react";
2
3function App() {
4 return (
5 <OpenLedgerProvider
6 entityId="your-entity-id"
7 accessToken={{
8 access_token: "your-access-token",
9 token_type: "Bearer",
10 expires_in: 3600,
11 expires_at: new Date(Date.now() + 3600 * 1000),
12 }}
13 environment="development"
14 apiUrl="https://api.openledger.com"
15 theme={{
16 primary: { hex: "#511320" },
17 accent: { hex: "#511320" },
18 background: { hex: "#FFFFFF" },
19 text: { hex: "#511320" },
20 secondary: { hex: "#7D4955" },
21 negative: { hex: "#B22222" },
22 }}
23 >
24 {/* Your application */}
25 </OpenLedgerProvider>
26 );
27}

Do not expose your API Key in the client. For production applications, implement a secure authentication flow where API keys are handled by your backend server to generate access tokens.

Generating Access Tokens

To generate an access token, make a request to the token endpoint from your backend:

1POST /v1/entities/auth/generate-token
2Content-Type: application/json
3
4{
5 "developerId": "your-developer-id",
6 "apiKey": "your-api-key",
7 "entityId": "your-entity-id"
8}

The response will include the access token that can be passed to your frontend:

1{
2 "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6...",
3 "token_type": "Bearer",
4 "expires_in": 3600
5}

Your frontend can then use this token:

1import { OpenLedgerProvider } from "@openledger/accounting-react";
2
3function App() {
4 // Get token from your auth system
5 const token = getTokenFromYourAuthSystem();
6
7 return (
8 <OpenLedgerProvider
9 entityId="your-entity-id"
10 accessToken={token}
11 environment="development"
12 apiUrl="https://api.openledger.com"
13 >
14 {/* Your application */}
15 </OpenLedgerProvider>
16 );
17}

Auth Error Handling

You can handle authentication errors by providing an onAuthError callback:

1import { OpenLedgerProvider } from "@openledger/accounting-react";
2
3function App() {
4 const handleAuthError = (error) => {
5 console.error("Authentication error:", error);
6 // Redirect to login page or show error message
7 };
8
9 return (
10 <OpenLedgerProvider
11 entityId="your-entity-id"
12 accessToken={token}
13 onAuthError={handleAuthError}
14 environment="development"
15 >
16 {/* Your application */}
17 </OpenLedgerProvider>
18 );
19}

Checking Auth Status

You can use the useOpenLedgerContext hook to check authentication status:

1import { useOpenLedgerContext } from "@openledger/accounting-react";
2
3function AuthStatus() {
4 const { auth, authLoading, authError } = useOpenLedgerContext();
5
6 if (authLoading) {
7 return <div>Authenticating...</div>;
8 }
9
10 if (authError) {
11 return <div>Authentication error: {authError.message}</div>;
12 }
13
14 if (auth) {
15 return <div>Authenticated successfully!</div>;
16 }
17
18 return <div>Not authenticated</div>;
19}

Authentication Security Best Practices

For production applications, consider these security best practices:

Backend Authentication

Implement token exchange on your backend to avoid exposing credentials in client-side code

Environment Variables

Use environment variables to store sensitive credentials (for server-side rendering)

Short-lived Tokens

Use short-lived access tokens and implement token refresh mechanisms

HTTPS Only

Ensure all communication happens over HTTPS

For production applications, we recommend implementing the following authentication flow:

  1. Your frontend application handles authentication, client requests access token from your backend
  2. Your backend authenticates with Open Ledger to retrieve access token
  3. Your backend receives and returns an access token to your frontend
  4. Your frontend initializes the SDK with this access token

This approach ensures your enterprise credentials remain secure on your backend server.

For sample implementation of secure authentication flows, check out our example repositories.

Environment Configuration

The SDK supports different environments to facilitate your development workflow:

EnvironmentDescriptionWhen to Use
developmentDevelopment environment with test dataDuring initial development and testing
productionLive production environmentFor production applications

Make sure to use the appropriate API URL and credentials for each environment. Credentials from one environment won’t work in another.

Full Configuration Options

The SDK provides several configuration options to customize its behavior:

1<OpenLedgerProvider
2 entityId="your-entity-id"
3 accessToken={{
4 access_token: "your-access-token",
5 token_type: "Bearer",
6 expires_in: 3600,
7 expires_at: new Date(Date.now() + 3600 * 1000),
8 }}
9 onAuthError={handleAuthError}
10 environment="development"
11 apiUrl="https://api.openledger.com"
12 theme={{
13 primary: { hex: "#511320" },
14 accent: { hex: "#511320" },
15 background: { hex: "#FFFFFF" },
16 text: { hex: "#511320" },
17 secondary: { hex: "#7D4955" },
18 negative: { hex: "#B22222" },
19 }}
20>
21 {/* Your application components */}
22</OpenLedgerProvider>

Theme Configuration

You can customize the appearance of components by providing a theme object:

1const customTheme = {
2 primary: { hex: "#4F46E5" },
3 secondary: { hex: "#10B981" },
4 accent: { hex: "#4F46E5" },
5 background: { hex: "#FFFFFF" },
6 text: { hex: "#1F2937" },
7 negative: { hex: "#EF4444" },
8 positive: { hex: "#10B981" },
9};
10
11<OpenLedgerProvider
12 entityId="your-entity-id"
13 accessToken={{
14 access_token: "your-access-token",
15 token_type: "Bearer",
16 expires_in: 3600,
17 expires_at: new Date(Date.now() + 3600 * 1000),
18 }}
19 onAuthError={handleAuthError}
20 environment="development"
21 theme={customTheme}
22>
23 {/* Your application components */}
24</OpenLedgerProvider>;

For detailed theme customization options, see the Theming Guide.

Error Handling

You can provide custom error handlers to manage authentication and other errors:

1<OpenLedgerProvider
2 entityId="your-entity-id"
3 accessToken={token}
4 onAuthError={(error) => {
5 console.error("Authentication error:", error);
6 // Redirect to login page or show error message
7 window.location.href = "/login";
8 }}
9>
10 {/* Your application components */}
11</OpenLedgerProvider>

Configuration with React Context

You can access configuration values within your components using the useOpenLedgerContext hook:

1import { useOpenLedgerContext } from "@openledger/accounting-react";
2
3function ConfigDisplay() {
4 const { entityId, environment, theme } = useOpenLedgerContext();
5
6 return (
7 <div>
8 <p>Entity ID: {entityId}</p>
9 <p>Environment: {environment}</p>
10 <p>Theme Primary Color: {theme.colors.primary}</p>
11 </div>
12 );
13}

Dynamic Configuration

For applications that need to change configuration at runtime:

1import { useState, useEffect } from "react";
2import { OpenLedgerProvider } from "@openledger/accounting-react";
3
4function App() {
5 const [config, setConfig] = useState({
6 entityId: null,
7 developerId: null,
8 developerSecret: null,
9 environment: "development",
10 });
11
12 useEffect(() => {
13 // Fetch configuration from your backend or local storage
14 async function fetchConfig() {
15 const response = await fetch("/api/config");
16 const data = await response.json();
17 setConfig(data);
18 }
19
20 fetchConfig();
21 }, []);
22
23 // Only render when configuration is loaded
24 if (!config.entityId) {
25 return <div>Loading configuration...</div>;
26 }
27
28 return (
29 <OpenLedgerProvider
30 entityId={config.entityId}
31 developerId={config.developerId}
32 developerSecret={config.developerSecret}
33 environment={config.environment}
34 >
35 {/* Your application components */}
36 </OpenLedgerProvider>
37 );
38}

Configuration Best Practices

For production applications, consider these configuration best practices:

Secure Backend Authentication

For client-side applications, implement a secure backend service that handles authentication:

1// Frontend
2async function getAccessToken() {
3 const response = await fetch("/api/get-open-ledger-token");
4 const { accessToken } = await response.json();
5 return accessToken;
6}
7
8function App() {
9 const [accessToken, setAccessToken] = useState(null);
10
11 useEffect(() => {
12 getAccessToken().then(setAccessToken);
13 }, []);
14
15 if (!accessToken) {
16 return <div>Authenticating...</div>;
17 }
18
19 return (
20 <OpenLedgerProvider
21 entityId="your-entity-id"
22 accessToken={accessToken}
23 environment="production"
24 >
25 {/* Your application components */}
26 </OpenLedgerProvider>
27 );
28}
29
30// Backend (Node.js/Express)
31app.get("/api/get-open-ledger-token", async (req, res) => {
32 // Use environment variables for sensitive credentials
33 const developerId = process.env.OPENLEDGER_DEVELOPER_ID;
34 const apiKey = process.env.OPENLEDGER_API_KEY;
35 const entityId = req.query.entityId || process.env.OPENLEDGER_ENTITY_ID;
36
37 try {
38 // Exchange credentials for an access token
39 const response = await fetch(
40 "https://api.openledger.com/v1/entities/auth/generate-token",
41 {
42 method: "POST",
43 headers: { "Content-Type": "application/json" },
44 body: JSON.stringify({
45 developerId,
46 apiKey,
47 entityId,
48 }),
49 }
50 );
51
52 const data = await response.json();
53
54 res.json({
55 accessToken: {
56 access_token: data.access_token,
57 token_type: data.token_type,
58 expires_in: data.expires_in,
59 expires_at: new Date(Date.now() + data.expires_in * 1000),
60 },
61 });
62 } catch (error) {
63 console.error("Error getting access token:", error);
64 res.status(500).json({ error: "Authentication failed" });
65 }
66});