1"use strict";(globalThis.webpackChunkschulconnex=globalThis.webpackChunkschulconnex||[]).push([[1106],{24333(e,n,t){t.r(n),t.d(n,{assets:()=>h,contentTitle:()=>c,default:()=>a,frontMatter:()=>d,metadata:()=>i,toc:()=>o});const i=JSON.parse('{"id":"schnittstellen/autorisierung-dienste","title":"Autorisierung Dienstanbieter","description":"Die Autorisierung entspricht dem Standard OAuth-Modell und ist im folgenden Sequenzdiagramm","source":"@site/docs/schnittstellen/autorisierung-dienste.md","sourceDirName":"schnittstellen","slug":"/schnittstellen/autorisierung-dienste","permalink":"/docs/schnittstellen/autorisierung-dienste","draft":false,"unlisted":false,"tags":[{"inline":true,"label":"Informativ","permalink":"/docs/tags/informativ"}],"version":"current","frontMatter":{"title":"Autorisierung Dienstanbieter","tags":["Informativ"]},"sidebar":"spezDiensteSidebar","previous":{"title":"HTTP-Statuscodes","permalink":"/docs/schnittstellendefinition/http-statuscodes-dienste"},"next":{"title":"OIDC-Claims","permalink":"/docs/schnittstellen/oidc-claims"}}');var r=t(74848),s=t(28453);const d={title:"Autorisierung Dienstanbieter",tags:["Informativ"]},c="API-Autorisierung und Authentifikation bei Dienstanbietern",h={},o=[{value:"Access Token",id:"access-token",level:2},{value:"ID Token",id:"id-token",level:2}];function l(e){const n={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",header:"header",mermaid:"mermaid",p:"p",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",...(0,s.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.header,{children:(0,r.jsx)(n.h1,{id:"api-autorisierung-und-authentifikation-bei-dienstanbietern",children:"API-Autorisierung und Authentifikation bei Dienstanbietern"})}),"\n",(0,r.jsxs)(n.p,{children:["Die Autorisierung entspricht dem Standard OAuth-Modell und ist im folgenden Sequenzdiagramm\ndargestellt. Danach werden die beiden Attribut-Listen \u201eAccess Token\u201c basierend auf der\nSpezifikation ",(0,r.jsx)(n.a,{href:"https://datatracker.ietf.org/doc/html/rfc6749",children:"OAuth 2.0 Authorization Framework"})," sowie \u201eID Token\u201c gem\xe4\xdf der Spezifikation\n",(0,r.jsx)(n.a,{href:"https://openid.net/specs/openid-connect-core-1_0.html",children:"OpenID Connect 1.0"})," definiert, jeweils mit spezifischen Anpassungen."]}),"\n",(0,r.jsx)(n.p,{children:"F\xfcr die Nutzung der in diesem Dokument spezifizierten Schnittstellenendpunkte (REST-APIs) des\nSchulconnex-Servers ist ein Access Token notwendig. Dieser wird von einem separaten\nAuthentication-Dienst ausgestellt. Den konkreten Endpunkt des Authentication-Dienstes\nerhalten Sie vom Betreiber des Schulconnex-Servers."}),"\n",(0,r.jsxs)(n.p,{children:["F\xfcr die Autorisierung eines Dienstes und die Authentifikation einer nutzenden Person gegen\xfcber\nder REST-API wird das OAuth 2.0 Protokoll verwendet. Gem\xe4\xdf der Spezifikation ",(0,r.jsx)(n.a,{href:"https://datatracker.ietf.org/doc/html/rfc6749",children:"IETF RFC 6749"}),"\n\u201eThe OAuth 2.0 Authorization Framework\u201d muss der REST-API-Endpunkt f\xfcr den \u201eOAuth 2.0 Token Exchange\u201c\n(siehe ",(0,r.jsx)(n.a,{href:"https://datatracker.ietf.org/doc/html/rfc8693",children:"IETF RFC 8693"})," \u201dOAuth 2.0 Token Exchange\u201d) genutzt werden. \xdcber die Schnittstelle wird\neiner Client-Anwendung im Erfolgsfall ein JSON mit Token ausgestellt; dieser beinhaltet unter\nanderem die Autorisierung eines Dienstes (den OAuth ",(0,r.jsx)(n.code,{children:"access_token"}),")."]}),"\n",(0,r.jsx)(n.mermaid,{value:"sequenceDiagram\n autonumber\n actor N as User\n participant D as Dienst\n participant Auth as IdP\n participant API as Schulconnex REST API\n N->>D: Login ausw\xe4hlen\n D->>Auth: Autorisierung anfordern\n Auth->>N: Umleitung auf Login-Seite des Identit\xe4tsproviders\n N->>Auth: Einloggen und zustimmen\n Auth->>D: Autorisierungscode\n D->>Auth: Autorisierungscode + Client ID + Client_Secret\n Auth->>Auth: Validierung\n Auth->>D: Access Token\n D->>API: Access Token\n API->>D: Antwort"}),"\n",(0,r.jsxs)(n.p,{children:["Die Attribute f\xfcr den erfolgreichen OAuth 2.0 Token Exchange sind im Unterkapitel\n\u201e",(0,r.jsx)(n.a,{href:"/docs/schnittstellen/autorisierung-dienste#access-token",children:"Access Token"}),"\u201c definiert. Bei dem ",(0,r.jsx)(n.code,{children:"access_token"}),"\nhandelt es sich um eine Zugriffsberechtigung in Form einer Zeichenkette, welche von den\nClient-Anwendungen bei den darauffolgenden HTTP-Anfragen gegen die REST-API im Authorization\nHeader verwendet wird (siehe Attribut ",(0,r.jsx)(n.code,{children:"token_type"}),"); dies ist in ",(0,r.jsx)(n.a,{href:"https://datatracker.ietf.org/doc/html/rfc6750",children:"IETF RFC 6750"}),"\n\u201eThe OAuth 2.0 Authorization Framework: Bearer Token Usage\u201c spezifiziert."]}),"\n",(0,r.jsxs)(n.p,{children:["Das ID Token f\xfchrt unter anderem das Attribut ",(0,r.jsx)(n.code,{children:"sub"})," (kurz f\xfcr subject identifier). Der Wert des\nAttributs ",(0,r.jsx)(n.code,{children:"sub"})," entspricht einer f\xfcr die Client-Anwendung pseudonymisierten ID ",(0,r.jsx)(n.code,{children:"pid"})," der angemeldeten\nnutzenden Person im gew\xe4hlten Sicherheitskontext. Das Datenmodell f\xfcr den ",(0,r.jsx)(n.code,{children:"id_token"})," ist im\nUnterkapitel \u201e",(0,r.jsx)(n.a,{href:"/docs/schnittstellen/autorisierung-dienste#id-token",children:"ID Token"}),"\u201c beschrieben."]}),"\n",(0,r.jsxs)(n.p,{children:["Dieser ID Token wird bei der Autorisierung eines Dienstes im Sicherheitskontext einer angemeldeten\nNutzerperson (",(0,r.jsx)(n.a,{href:"https://datatracker.ietf.org/doc/html/rfc6749#section-1.3.1",children:"OAuth 2.0 Authorization Code Grant"}),") ausgestellt und als Attribut ",(0,r.jsx)(n.code,{children:"id_token"})," im JSON\nder erfolgreichen OAuth 2.0 Token Exchange Anfrage gef\xfchrt. Der f\xfcr die Client-Anwendung pseudonymisierte\nIdentifier (Id) der nutzenden Person beschreibt die Person im Sicherheitskontext der Anmeldung und ist\nals Attribut ",(0,r.jsx)(n.code,{children:"sub"})," im ",(0,r.jsx)(n.code,{children:"id_token"})," enthalten."]}),"\n",(0,r.jsxs)(n.p,{children:["In einigen F\xe4llen ist es f\xfcr Dienstanbieter w\xfcnschenswert, neben der PID bereits bei der\nAutorisierung weitere Informationen \xfcber die angemeldete Person zu erhalten. Dies kann, nach\nAbsprache mit dem Betreiber des Schulconnex-Servers, durch die Nutzung von OIDC Claims geschehen.\nDie Nutzung von OIDC Claims zur \xdcbermittlung von Schulconnex-Informationen ist in Kapitel\n\u201e",(0,r.jsx)(n.a,{href:"/docs/schnittstellen/oidc-claims",children:"Person-Info \xfcber OIDC Claims"}),"\u201c beschrieben. Im Regelfall sollten\naber die REST-APIs zur Abfrage von Informationen genutzt werden."]}),"\n",(0,r.jsxs)(n.p,{children:["F\xfcr darauffolgende Anfragen der Client-Anwendungen gegen einen API-Endpunkt des Schulconnex-Services\nmuss der ",(0,r.jsx)(n.code,{children:"access_token"})," als Authorization Header im XMLHttpRequest (XHR) verwendet werden.\nDas Attribut ",(0,r.jsx)(n.code,{children:"token_type"})," beim OAuth 2.0 Token Exchange Request referenziert die Art der Verwendung\ndes ",(0,r.jsx)(n.code,{children:"access_token"})," \u2013 gem\xe4\xdf IETF RFC 6750 \u201eThe OAuth 2.0 Authorization Framework: Bearer Token Usage\u201c oder\nden ",(0,r.jsx)(n.a,{href:"https://datatracker.ietf.org/doc/html/rfc7617",children:"Basic"})," und ",(0,r.jsx)(n.a,{href:"https://datatracker.ietf.org/doc/html/rfc7616",children:"Digest"})," Authentifizierungsschemata."]}),"\n",(0,r.jsxs)(n.p,{children:["Im Kontext der Spezifikation OpenID Connect muss das Attribut ",(0,r.jsx)(n.code,{children:"token_type"})," den Wert ",(0,r.jsx)(n.code,{children:'"Bearer"'})," f\xfchren."]}),"\n",(0,r.jsx)(n.h2,{id:"access-token",children:"Access Token"}),"\n",(0,r.jsxs)(n.p,{children:["Die folgende Tabelle beschreibt die Attribute f\xfcr die JSON-Antwort einer OAuth\n2.0-Token-Exchange-Anfrage. Diese JSON-Struktur beinhaltet unter anderem die Autorisierung\neines Dienstangebots (den OAuth ",(0,r.jsx)(n.code,{children:"access_token"}),") und die Authentifikation einer nutzenden Person\n(den OpenID Connect ",(0,r.jsx)(n.code,{children:"id_token"}),"). Beim Berechtigungstyp \u201e",(0,r.jsx)(n.a,{href:"https://datatracker.ietf.org/doc/html/rfc6749#section-4.4",children:"OAuth 2.0 Client Credentials Grant"}),"\u201c\nwird vom Dienst ein Zugriffstoken (",(0,r.jsx)(n.code,{children:"access_token"}),") au\xdferhalb des Sicherheitskontexts einer\nangemeldeten nutzenden Person angefordert. In diesem Fall wird kein ",(0,r.jsx)(n.code,{children:"id_token"})," ausgestellt.\nBasierend auf der Spezifikation OAuth 2.0 ist der Antwort-Typ eines OAuth 2.0 Token Exchange\nein JSON-Dokument (HTTP ContentType ",(0,r.jsx)(n.code,{children:"application/json"}),"), welches der\n",(0,r.jsx)(n.a,{href:"https://datatracker.ietf.org/doc/html/rfc8693",children:"IETF RFC8693"}),"-Spezifikation entspricht."]}),"\n",(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"Attribut Ebene 0"}),(0,r.jsx)(n.th,{children:"Typ"}),(0,r.jsx)(n.th,{children:"Anzahl"}),(0,r.jsx)(n.th,{children:"Bemerkung"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"access_token"}),(0,r.jsx)(n.td,{children:"String (byte)"}),(0,r.jsx)(n.td,{children:"1"}),(0,r.jsxs)(n.td,{children:["Ein Token (",(0,r.jsx)(n.code,{children:"access_token"}),"), welches vom Service auf die OAuth 2.0-Token-Exchange-Anfrage im Erfolgsfall ausgestellt wurde. Dieses ausgestellte ",(0,r.jsx)(n.code,{children:"access_token"})," des zugrunde liegenden Authorization Frameworks ist spezifiziert in ",(0,r.jsx)(n.a,{href:"https://datatracker.ietf.org/doc/html/rfc6749#section-5.1",children:"IETF RFC6749"})," Abschnitt 5.1 ."]})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"expires_in"}),(0,r.jsx)(n.td,{children:"Integer"}),(0,r.jsx)(n.td,{children:"0..1"}),(0,r.jsxs)(n.td,{children:["Die G\xfcltigkeit des Tokens (",(0,r.jsx)(n.code,{children:"access_token"}),") in Sekunden ab Ausstellung. Das ",(0,r.jsx)(n.code,{children:"access_token"})," beinhaltet ebenfalls die Dauer der G\xfcltigkeit des Tokens. Dieser Wert ist ",(0,r.jsx)(n.em,{children:"optional"}),", sofern ein ",(0,r.jsx)(n.code,{children:"access_token"})," ausgestellt wurde. Beispielhaft steht der Wert 1800 f\xfcr eine G\xfcltigkeitsdauer von 30 Minuten."]})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"refresh_token"}),(0,r.jsx)(n.td,{children:"String (byte)"}),(0,r.jsx)(n.td,{children:"0..1"}),(0,r.jsxs)(n.td,{children:["Ein Token (",(0,r.jsx)(n.code,{children:"refresh_token"}),"), welches vom Schulconnex-Server auf die OAuth 2.0-Token-Exchange-Anfrage im Erfolgsfall ",(0,r.jsx)(n.em,{children:"optional"})," ausgestellt wurde. Mit dem ",(0,r.jsx)(n.code,{children:"refresh_token"})," kann beim Schulconnex-Server ein neues ",(0,r.jsx)(n.code,{children:"access_token"})," angefordert werden."]})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"token_type"}),(0,r.jsx)(n.td,{children:"String (Enumerated)"}),(0,r.jsx)(n.td,{children:"0..1"}),(0,r.jsxs)(n.td,{children:["Der ",(0,r.jsx)(n.code,{children:"token_type"})," stellt die Information zur Verf\xfcgung, wie das ",(0,r.jsx)(n.code,{children:"access_token"})," angewendet werden kann. Im Kontext der Spezifikation OpenID Connect ",(0,r.jsx)(n.em,{children:"muss"})," das Attribut ",(0,r.jsx)(n.code,{children:"token_type"})," den Wert ",(0,r.jsx)(n.a,{href:"https://datatracker.ietf.org/doc/html/rfc6750",children:(0,r.jsx)(n.code,{children:'"Bearer"'})})," f\xfchren."]})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"id_token"}),(0,r.jsx)(n.td,{children:"String (byte)"}),(0,r.jsx)(n.td,{children:"0..1"}),(0,r.jsxs)(n.td,{children:["Basierend auf der Spezifikation OpenID Connect beinhaltet die Token-Antwort einer OAuth 2.0-Token-Exchange-Anfrage zus\xe4tzlich ein Token (",(0,r.jsx)(n.a,{href:"https://openid.net/specs/openid-connect-core-1_0.html#CodeIDToken",children:(0,r.jsx)(n.code,{children:"id_token"})}),"), welches Informationen \xfcber die Authentifizierung einer nutzenden Person beinhaltet. Siehe \u201e",(0,r.jsx)(n.a,{href:"/docs/schnittstellen/autorisierung-dienste#id-token",children:"ID Token"}),"\u201c."]})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"scope"}),(0,r.jsx)(n.td,{children:"String (byte)"}),(0,r.jsx)(n.td,{children:"0..1"}),(0,r.jsxs)(n.td,{children:["Eine Liste von durch Leerzeichen getrennten Zeichenketten, die den ",(0,r.jsx)(n.a,{href:"https://datatracker.ietf.org/doc/html/rfc6749#section-3.3",children:"Geltungsbereich des Tokens"})," spezifiziert."]})]})]})]}),"\n",(0,r.jsx)(n.h2,{id:"id-token",children:"ID Token"}),"\n",(0,r.jsxs)(n.p,{children:["Die folgende Tabelle beschreibt die Attribute f\xfcr eine authentifizierte nutzende Person in Form\neines sogenannten OpenID Connect ID-Tokens. Bei dem ",(0,r.jsx)(n.code,{children:"id_token"})," handelt es sich um ein\n",(0,r.jsx)(n.a,{href:"https://datatracker.ietf.org/doc/html/rfc7519",children:"JSON Web Token (JWT)"}),". Von Interesse f\xfcr Dienstanbieter ist das Attribut ",(0,r.jsx)(n.code,{children:"sub"})," (subject identifier).\nBei dieser Zeichenkette handelt es sich um einen Identifier, welcher der authentifizierten\nnutzenden Person in dessen Sicherheitskontext und anfragenden Dienst nach der OpenID-Connect-Spezifikation\nals Subject-Identifier-Typ \u201epairwise\u201c zugeordnet ist (siehe Spezifikation ",(0,r.jsx)(n.a,{href:"https://openid.net/specs/openid-connect-core-1_0.html",children:"OpenID Connect 1.0"}),"\nKapitel 8.0 \u201eSubject Identifier Type\u201d und Kapitel 8.1 \u201ePairwise Identifier Algorithm\u201d der\nSpezifikation OpenID Connect 1.0)."]}),"\n",(0,r.jsxs)(n.table,{children:[(0,r.jsx)(n.thead,{children:(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.th,{children:"Attribut Ebene 0"}),(0,r.jsx)(n.th,{children:"Typ"}),(0,r.jsx)(n.th,{children:"Anzahl"}),(0,r.jsx)(n.th,{children:"Bemerkung"})]})}),(0,r.jsxs)(n.tbody,{children:[(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"iss"}),(0,r.jsx)(n.td,{children:"String (byte)"}),(0,r.jsx)(n.td,{children:"1"}),(0,r.jsx)(n.td,{children:"Der issuer identifier ist eine URL, welche denjenigen identifiziert, der die Inhalte herausgegeben hat."})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"sub"}),(0,r.jsx)(n.td,{children:"String (byte)"}),(0,r.jsx)(n.td,{children:"1"}),(0,r.jsx)(n.td,{children:"Der subject identifier ist eine Zeichenkette mit einer maximalen L\xe4nge von 255 ASCII-Zeichen und repr\xe4sentiert, wer lokal das Token nutzt."})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"aud"}),(0,r.jsx)(n.td,{children:"String (byte)"}),(0,r.jsx)(n.td,{children:"1"}),(0,r.jsxs)(n.td,{children:["Die audience (",(0,r.jsx)(n.code,{children:"aud"}),") claim listet die erwarteten Empf\xe4ngerinnen und Empf\xe4nger des JWT auf. Im Falle eines ID-Tokens enth\xe4lt aud die Client-ID der Client-Anwendung, welche den ID-Token angefordert hat."]})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"exp"}),(0,r.jsx)(n.td,{children:"Integer"}),(0,r.jsx)(n.td,{children:"1"}),(0,r.jsxs)(n.td,{children:["Das Attribut ",(0,r.jsx)(n.code,{children:"exp"})," (expires) f\xfchrt das Datum, bis wann das JWT G\xfcltigkeit hat. Das Datum wird als Unix-Epoch-Time gef\xfchrt und ist ein Integer, welcher die Sekunden seit dem 01. Januar 1970 angibt."]})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"iat"}),(0,r.jsx)(n.td,{children:"Integer"}),(0,r.jsx)(n.td,{children:"1"}),(0,r.jsxs)(n.td,{children:["Das Attribut ",(0,r.jsx)(n.code,{children:"iat"})," (issued at) f\xfchrt das Datum, zu welchem Zeitpunkt das JWT ausgestellt wurde. Das Datum wird als Unix-Epoch-Time gef\xfchrt und ist ein Integer, welcher die Sekunden seit dem 01. Januar 1970 angibt."]})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"auth_time"}),(0,r.jsx)(n.td,{children:"Integer"}),(0,r.jsx)(n.td,{children:"0..1"}),(0,r.jsxs)(n.td,{children:["Das optionale Attribut ",(0,r.jsx)(n.code,{children:"auth_time"})," f\xfchrt das Datum, zu welchem Zeitpunkt die nutzende Person authentifiziert wurde. Das Datum wird als Unix-Epoch-Time gef\xfchrt und ist ein Integer, welcher die Sekunden seit dem 01. Januar 1970 angibt."]})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"non
1ce"}),(0,r.jsx)(n.td,{children:"String (byte)"}),(0,r.jsx)(n.td,{children:"0..1"}),(0,r.jsxs)(n.td,{children:["ID-Token k\xf6nnen mit dem Attribut ",(0,r.jsx)(n.code,{children:"nonce"})," ausgestellt werden, um Attacken zu verhindern. Das optionale Attribut wird gef\xfchrt, sofern dieses bei der Ausstellung angefordert wurde und der Schulconnex-Service diesen entsprechend zum Abgleich vorh\xe4lt."]})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"acr"}),(0,r.jsx)(n.td,{children:"String (byte)"}),(0,r.jsx)(n.td,{children:"0..1"}),(0,r.jsxs)(n.td,{children:["Das optionale Attribut ",(0,r.jsx)(n.code,{children:"acr"})," (Authentication Context Class Reference) referenziert die URI der ",(0,r.jsx)(n.a,{href:"https://openid.net/specs/openid-provider-authentication-policy-extension-1_0.html",children:"Benutzerauthentifizierungsmethode"}),", welche erf\xfcllt wurde."]})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"amr"}),(0,r.jsx)(n.td,{children:"String (byte)"}),(0,r.jsx)(n.td,{children:"0..1"}),(0,r.jsxs)(n.td,{children:["Das optionale Attribut ",(0,r.jsx)(n.code,{children:"amr"})," (Authentication Method Reference) referenziert die Methode der ",(0,r.jsx)(n.a,{href:"https://datatracker.ietf.org/doc/html/rfc8176",children:"Benutzerauthentifizierung"}),", welche verwendet wurde."]})]}),(0,r.jsxs)(n.tr,{children:[(0,r.jsx)(n.td,{children:"azp"}),(0,r.jsx)(n.td,{children:"String (byte)"}),(0,r.jsx)(n.td,{children:"0..1"}),(0,r.jsxs)(n.td,{children:["Das optionale Attribut ",(0,r.jsx)(n.code,{children:"azp"})," (Authorized Party) f\xfchrt die Client-ID der autorisierten Anwendung; es handelt sich um die Client-ID des Clients, welche den ID-Token angefordert hat."]})]})]})]})]})}function a(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(l,{...e})}):l(e)}},28453(e,n,t){t.d(n,{R:()=>d,x:()=>c});var i=t(96540);const r={},s=i.createContext(r);function d(e){const n=i.useContext(s);return i.useMemo(function(){return"function"==typeof e?e(n):{...n,...e}},[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:d(e.components),i.createElement(s.Provider,{value:n},e.children)}}}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.