Haftungsausschluss: Dieser Artikel wurde durch maschinelle Übersetzung erstellt.

Implementiere JWT in deiner Anwendung

Prev Next

Nach Abschluss der JWT-Konfiguration in Document360 benötigt Ihre Anwendung eine Backend-Route, um den letzten Schritt des Login-Flows abzuwickeln.

Diese Route:

  • Es wird überprüft, dass der Benutzer bereits in Ihrer Anwendung authentifiziert ist
  • Sendet eine sichere Anfrage an die Code-Generierungs-URL von Document360
  • Ruft einen einmaligen Autorisierungscode ab
  • Leitet den Benutzer mit diesem Code auf die Wissensdatenbank-Seite um

HINWEIS

Leser benötigen kein separates Document360-Konto. Die Authentifizierung erfolgt vollständig über Ihre Anwendung. Ein Konto in Ihrer Anwendung reicht aus, damit ein Leser auf die Wissensdatenbank zugreifen kann.


Codebeispiele

Die untenstehenden Beispiele zeigen, wie man die Backend-Authentifizierungsroute in C#, Node.js und Java implementiert.

C #

/// <summary>
/// Example endpoint to authenticate a user and retrieve a token from the identity server,
/// and redirect the user to the Knowledge Base (KB) using the token code.
/// </summary>
/// <param name="clientId">Client ID issued for your application</param>
/// <param name="clientSecret">Client secret associated with the client ID</param>
/// <returns>Redirects to the KB with the issued code</returns>
[HttpGet]
[Route("authenticate")]
public async Task<IActionResult> AuthenticateAsync(string clientId, string clientSecret)
{
    if (!HttpContext.User.Identity.IsAuthenticated)
    {
        // user is not authenticated, redirect to an error or login page
        return Unauthorized(new { message = "User not authenticated" });
    }

    // Ensure you have the correct client ID and secret from your Document360 JWT configuration
    var authToken = Encoding.ASCII.GetBytes($"{clientId}:{clientSecret}");

    // Create an HttpClient instance
    using var httpClient = new HttpClient();

    // Set the Authorization header with Basic authentication
    httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(authToken));

    // Prepare the payload with user information
    var payload = new
    {
        username = User.Identity.Name,
        firstName = "FirstName", // Replace or customize as needed
        lastName = "LastName",
        emailId = "user@example.com", // Replace with actual user email
        readerGroupIds = new List<string> { "group1", "group2" }, // Replace with actual reader group IDs if needed (Optional)
        tokenValidity = 3600, // Token validity in seconds (Optional, default is 5 minutes)
        providerName = "app.example.com" // Domain of the matching JWT configuration (Required when multiple JWT configurations are active)
    };

    var payloadContent = new StringContent(JsonConvert.SerializeObject(payload), Encoding.UTF8, "application/json");

    // Identity server token endpoint - replace with your actual URL
    string identityServerUrl = "codeGeneration endpoint, you can find that in JWT config portal";
    // KB login URL to redirect after successful token issuance
    string kbLoginUrl = "https://{your subdomain}.document360.io";

    var response = await httpClient.PostAsync(identityServerUrl, payloadContent);

    if (response.IsSuccessStatusCode)
    {
        var content = await response.Content.ReadAsStringAsync();
        var tokenJson = JObject.Parse(content);
        // Extract the code from the response
        var tokenCode = (string)tokenJson.SelectToken("code");

        // Construct the KB login URL with code query parameter
        string finalRedirectUrl = $"{kbLoginUrl}?code={tokenCode}";

        return Redirect(finalRedirectUrl);
    }
    else
    {
        // Handle error response from the identity server
        var error = await response.Content.ReadAsStringAsync();
        return StatusCode((int)response.StatusCode, new { error = "Token request failed", details = error });
    }
}

Node.js

const express = require('express');
const https = require('https');
const axios = require('axios');
const app = express();

app.use(express.json());

const clientId = 'your-client-id';
const clientSecret = 'your-client-secret';
const codeGenerationUrl = 'https://identity.document360.net/jwt/generateCode';
const kbLoginUrl = 'https://your-subdomain.document360.net/jwt/authorize';

app.get('/authenticate', async (req, res) => {
  try {
    const isAuthenticated = true; // Replace with your actual auth logic

    if (!isAuthenticated) {
      return res.status(401).json({ message: 'User not authenticated' });
    }

    const authHeader = Buffer.from(`${clientId}:${clientSecret}`).toString('base64');

    const payload = {
      username: 'john.doe',
      firstName: 'John',
      lastName: 'Doe',
      emailId: 'john.doe@example.com',
      readerGroupIds: ['group1', 'group2'],
      tokenValidity: 3600,
      providerName: 'app.example.com' // Domain of the matching JWT configuration
    };

    const response = await axios.post(
      codeGenerationUrl,
      payload,
      {
        headers: {
          'Authorization': `Basic ${authHeader}`,
          'Content-Type': 'application/json',
          'Accept': 'application/json'
        },
        httpsAgent: new https.Agent({ maxVersion: 'TLSv1.2' })
      }
    );

    const tokenCode = response.data?.code;

    if (!tokenCode) {
      return res.status(500).json({ message: 'No code received from Document360' });
    }

    console.log("Redirecting to:", `${kbLoginUrl}?code=${tokenCode}`);
    return res.redirect(`${kbLoginUrl}?code=${tokenCode}`);

  } catch (error) {
    return res.status(500).json({
      message: 'JWT SSO failed',
      details: error.response?.data || error.message
    });
  }
});

Java

import org.springframework.http.*;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

import java.nio.charset.StandardCharsets;
import java.util.*;

@RestController
public class JwtSsoController {

    private final String clientId = "your-client-id";
    private final String clientSecret = "your-client-secret";
    private final String codeGenerationUrl = "https://identity.document360.io/api/jwt/generate-code";
    private final String kbLoginUrl = "https://your-subdomain.document360.io/jwt/authorize";

    @GetMapping("/authenticate")
    public ResponseEntity<?> authenticate() {
        // Example: Check if user is authenticated in your system
        boolean isAuthenticated = true; // Replace with actual logic
        if (!isAuthenticated) {
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("User not authenticated");
        }

        // Create Basic Auth header
        String auth = clientId + ":" + clientSecret;
        String encodedAuth = Base64.getEncoder().encodeToString(auth.getBytes(StandardCharsets.UTF_8));
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.set("Authorization", "Basic " + encodedAuth);
        headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));

        // Construct payload
        Map<String, Object> payload = new HashMap<>();
        payload.put("username", "john.doe");
        payload.put("firstName", "John");
        payload.put("lastName", "Doe");
        payload.put("emailId", "john.doe@example.com");
        payload.put("readerGroupIds", Arrays.asList("group1", "group2"));
        payload.put("tokenValidity", 3600);
        payload.put("providerName", "app.example.com"); // Domain of the matching JWT configuration

        HttpEntity<Map<String, Object>> request = new HttpEntity<>(payload, headers);
        RestTemplate restTemplate = new RestTemplate();

        try {
            ResponseEntity<Map> response = restTemplate.postForEntity(codeGenerationUrl, request, Map.class);

            if (response.getStatusCode() == HttpStatus.OK && response.getBody() != null) {
                String tokenCode = (String) response.getBody().get("code");

                if (tokenCode == null || tokenCode.isEmpty()) {
                    return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                            .body("No code returned from Document360");
                }

                // Redirect to the KB site with code
                String redirectUrl = UriComponentsBuilder.fromHttpUrl(kbLoginUrl)
                        .queryParam("code", tokenCode)
                        .toUriString();

                HttpHeaders redirectHeaders = new HttpHeaders();
                redirectHeaders.setLocation(java.net.URI.create(redirectUrl));
                return new ResponseEntity<>(redirectHeaders, HttpStatus.FOUND);

            } else {
                return ResponseEntity.status(HttpStatus.BAD_GATEWAY)
                        .body("Failed to get code from Document360: " + response.getStatusCode());
            }

        } catch (Exception ex) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                    .body("JWT SSO error: " + ex.getMessage());
        }
    }
}

Re-Authentifizierung von Lesern mit mehreren JWT-Konfigurationen

Wenn die Sitzung eines Lesers abläuft, schickt Document360 ihn erneut zum Anmelden. Die Weiterleitung hängt davon ab, wie viele JWT-Konfigurationen in Ihrem Projekt aktiv sind:

  • Eine JWT-Konfiguration: Document360 leitet den Leser direkt auf die konfigurierte Login-URL um.
  • Mehrere JWT-Konfigurationen: Document360 kann nicht erkennen, durch welche Konfiguration der Reader sich angemeldet hat, sodass der Reader auf einer Anmeldeseite landet und seine Domain eingeben muss.

Um die Leser direkt zur korrekten Login-URL zurückzuschicken, fügen Sie der Nutzlast, die Ihr Backend sendet, zur Code-Generierungs-URL hinzu providerName . Setzen Sie ihren Wert auf die Domain der passenden JWT-Konfiguration, die in Einstellungen > Users & Permissions > JWT verfügbar ist.

{
  "username": "john.doe",
  "firstName": "John",
  "lastName": "Doe",
  "emailId": "john.doe@example.com",
  "readerGroupIds": ["group1", "group2"],
  "tokenValidity": 3600,
  "providerName": "app.example.com"
}

Wie es funktioniert

  1. Deine Bewerbung wird gesendet, providerName wenn der Leser sich anmeldet.
  2. Document360 zeichnet die JWT-Konfiguration auf, durch die sich der Leser angemeldet hat.
  3. Wenn die Sitzung abläuft, leitet Document360 den Leser direkt auf die Login-URL dieser Konfiguration um, ohne die Domain-Eingangsseite anzuzeigen.

HINWEIS

Wenn dein Projekt nur eine JWT-Konfiguration hat, providerName ist das optional. Document360 leitet die Leser bereits bei Ablauf der Sitzung auf die konfigurierte Login-URL um.


Entwickler-Checkliste

Überprüfen Sie vor dem Live-Start Folgendes:

  • Registrieren Sie die Login-URL, die Rückruf-URL und die Code-Generierungs-URL in Ihren JWT-Einstellungen.
  • Bewahren Sie das Client-Geheimnis sicher auf. Es wird zum Zeitpunkt der Erstellung nur einmal angezeigt.
  • Implementiere Backend-Logik, um die Codegenerierungs-URL mit HTTP Basic Auth aufzurufen.
  • Signiere das JWT in deinem Backend mit deinem Client Secret. Mach niemals Signing-Logik auf der Client-Seite sichtbar.
  • Wenn Ihr Projekt mehrere JWT-Konfigurationen hat, fügen Sie in die Nutzlast die Domäne der passenden Konfiguration ein.providerName
  • Setzen Sie HTTPS auf allen Endpunkten durch, die am Authentifizierungsfluss beteiligt sind.
  • Testsitzungsverhalten, Token-Ablauf und automatische Sitzungsverlängerung vor dem Live-Gehen.
  • Überwachen Sie Backend-Protokolle auf 401-Fehler, die typischerweise auf abgelaufene Autorisierungscodes oder Token-Missmatches hinweisen.

Weiterleitung auf eine bestimmte Seite nach dem Anmelden

Standardmäßig werden die Leser nach dem Einloggen auf die Startseite Ihrer Wissensdatenbank weitergeleitet.

  • Wenn Ihre Startseite unveröffentlicht ist, werden die Leser auf die Seite /docs weitergeleitet.
  • Um Leser auf eine andere Seite in Ihrer Wissensdatenbank umzuleiten, konfigurieren Sie die Weiterleitung mit dem folgenden URL-Muster.

URL-Muster

https://<Knowledge base URL>/jwt/authorize?code=<code>&redirectUrl=<redirect path>

Parameter

  • <Knowledge base URL>: Die Haupt-URL Ihrer Wissensdatenbank-Website.
  • <code>: der Code, der vom Document360-Code-Generierungsendpunkt generiert wird.
  • <redirect path>: Die URL, auf die Sie die Leser nach dem Login landen sollen.

Beispiel

https://example.document360.io/jwt/authorize?code=FOTaS_SW6dLGytQXvrG_rRFGhyPvrDDrgxJAZzYvJcY&redirectUrl=/docs/5-basic-things-to-get-started

HINWEIS

Document360 sendet die Umleitungs-URL an den Login-Endpunkt redirectPath . Wenn der Login-Endpunkt mit dem Authentifizierungscode zur Wissensdatenbank zurückleitet, sollte er die Umleitungs-URL als Parameter redirectUrl zurückgeben.

In KB Site 2.0 wird die Weiterleitung über Cookies statt über den Parameter redirectUrl gehandhabt. Wenn Ihre JWT-Implementierung auf der Abfrage-String-Weiterleitung mit dem Parameter redirectUrl basiert, unterstützt der cookie-basierte Ansatz diesen Parameter nicht. Sie müssen möglicherweise Ihre Implementierung aktualisieren oder den Support für weitere Klarstellungen kontaktieren .