Wie macht man Single Sign On mit FPC ?

Alle Fragen zur Netzwerkkommunikation
Antworten
Benutzeravatar
corpsman
Lazarusforum e. V.
Beiträge: 1496
Registriert: Sa 28. Feb 2009, 08:54
OS, Lazarus, FPC: Linux Mint Mate, Lazarus GIT Head, FPC 3.0
CPU-Target: 64Bit
Wohnort: Stuttgart
Kontaktdaten:

Wie macht man Single Sign On mit FPC ?

Beitrag von corpsman »

Servus zusammen,
Dank der neuen Arbeitszeitgesetzt ist mein Arbeitgeber auf ein neues Tool zum Arbeitszeiten verwalten umgestiegen.

Da aber irgendwie alle Tools doof sind, hatte ich für mich und auch meine Kollegen ein eigenes Lazarus Tool gebastelt, was tatsächlich Benutzbar und schlank ist.

Nun hat das neue Tool aber keinen Login via SSH mehr sondern dieses Ominöse Single Sign On.

Wie ich das mit der SSH Variante gemacht hatte habe ich auch hier versucht das ganze von "Hand" nach zu bauen, doch leider antwortet mir der Server mit 403 :(


Kennt jemand eine Lazarus Kompenente die sowas kann ? (oder kan Synapse das evtl schon und ich habs nur nicht gefunden ?)

Code: Alles auswählen


Function TSTIHLATOSS.Login: Boolean;
Var
  _Action: String;
  _RelayState: String;
  _Host: String;
  _SAMLRequest: String;

  Procedure ExctractLoginAction();
  Var
    sl: TStringList;
    tmp, Prot, User, Pass, Host, Port, Path, Para: String;
    i: Integer;
  Begin
    _Action := '';
    _RelayState := '';
    _SAMLRequest := '';
    Host := '';
    sl := TStringList.Create;
    CopyStreamToStrings(fClient.Document, sl);
    // sl.SaveToFile('C:\Desktop\ExctractLoginAction.txt'); // Debugg, to be removed
    For i := 0 To sl.count - 1 Do Begin
      If pos('form action="', sl[i]) <> 0 Then Begin
        tmp := copy(sl[i], pos('"', sl[i]) + 1, length(sl[i]));
        tmp := copy(tmp, 1, pos('"', tmp) - 1);
        _Action := DecodeUTF8EntityString(tmp); 
      End;
      If pos('name="RelayState"', sl[i]) <> 0 Then Begin
        tmp := copy(sl[i], pos('value=', sl[i]), length(sl[i]));
        tmp := copy(tmp, pos('"', tmp) + 1, length(tmp));
        tmp := copy(tmp, 1, pos('"', tmp) - 1);
        _RelayState := tmp; 
        ParseURL(DecodeUTF8EntityString(tmp), Prot, User, Pass, Host, Port, Path, Para);
        _Host := Prot + '://' + Host;
      End;
      // <input type="hidden" name="SAMLRequest" value="PDc3Q+"/>
      If pos('name="SAMLRequest"', sl[i]) <> 0 Then Begin
        tmp := copy(sl[i], pos('value=', sl[i]), length(sl[i]));
        tmp := copy(tmp, pos('"', tmp) + 1, length(tmp));
        tmp := copy(tmp, 1, pos('"', tmp) - 1);
        _SAMLRequest := tmp; // = PDc3Q+
      End;
    End;
    sl.free;
  End;
Var
  Body: TStringlist;
Begin
  result := false;
  fLoggedIn := false;
  fLastError := '';
  If assigned(fClient) Then fClient.Free;
  fClient := THTTPSend.Create;
  fClient.KeepAlive := true; // Braucht man das, ich weis es nicht ?
  fClient.Cookies.Clear;
  fClient.Headers.Clear;
  // 1. Anfragen der Login Daten
  fClient.HTTPMethod('GET', LoginURL);
  ExctractLoginAction();
  // 2. Auslesen der Post Anfrage Daten
  If (_Action = '') Or
    (_RelayState = '') Or
    (_SAMLRequest = '') Then Begin
    fLastError := 'Could not extract action links.';
    exit;
  End;
  If (fClient.ResultCode <> 200) Then Begin
    fLastError := 'HTTP.ResultCode: ' + inttostr(fClient.ResultCode) + ' ; ' + fClient.ResultString + LineEnding +
      'HTTP.Sock.LastError: ' + inttostr(fClient.Sock.LastError) + ' ; ' + fClient.Sock.LastErrorDesc + LineEnding +
      'HTTP.Sock.SSL.LastError: ' + inttostr(fClient.Sock.SSL.LastError) + ' ; ' + fClient.Sock.SSL.LastErrorDesc;
    (*
     * Wenns nicht klappt, eine Abhilfe schafft evtl:
     *
     *   sudo aptitude install libssl-dev
     *)
    exit;
  End;
  Body := TStringList.Create;
  body.text := 'SAMLResponse=' + _SAMLRequest +
    '&RelayState=' + _RelayState;
  fClient.MimeType := 'application/x-www-form-urlencoded';
  fClient.Document.Clear;
  fClient.Headers.Clear;
  CopyStringsToStream(body, fClient.Document);
//  body.SaveToFile('C:\Desktop\SAML_Body.txt'); // Debugg, to be removed
  body.free;
  fclient.UserAgent := 'Mozilla/5.0 (Windows NT 10.0; …) Gecko/20100101 Firefox/60.0'; // -- Manchmal akzeptieren die Gegenstellen nicht, das wir Synaptik sind.
  fClient.HTTPMethod('POST', _Host + SSOFilename); // <-- Hier kommt die 403 Antwort, wo im Firefox alles aktzepiert wird
  body := TStringList.Create;
  CopyStreamToStrings(fClient.Document, body);
  body.SaveToFile('C:\Desktop\Nach_Post_vor_Follow.txt'); // Debugg, to be removed
  body.free;
  Follow_Links(_Host + SSOFilename);
  body := TStringList.Create;
  CopyStreamToStrings(fClient.Document, body);
  body.SaveToFile('C:\Desktop\Nach_Post_nach_Follow.txt'); // Debugg, to be removed
  body.free;

  //sl.Clear;
  //CopyStreamToStrings(fClient.Document, sl);
  //sl.SaveToFile('C:\Desktop\Nach_Follow.txt');
  //sl.free;


End;   
Zuletzt geändert von corpsman am Fr 3. Feb 2023, 14:00, insgesamt 1-mal geändert.
--
Just try it

Benutzeravatar
theo
Beiträge: 10467
Registriert: Mo 11. Sep 2006, 19:01

Re: Wie macht man Single Sign On mit FPC ?

Beitrag von theo »

Ist das nicht eher ein Überbegriff?

Es gibt z.B. Unit fpoauth2
S.a.
https://forum.lazarus.freepascal.org/in ... ic=55962.0

Benutzeravatar
corpsman
Lazarusforum e. V.
Beiträge: 1496
Registriert: Sa 28. Feb 2009, 08:54
OS, Lazarus, FPC: Linux Mint Mate, Lazarus GIT Head, FPC 3.0
CPU-Target: 64Bit
Wohnort: Stuttgart
Kontaktdaten:

Re: Wie macht man Single Sign On mit FPC ?

Beitrag von corpsman »

OK nach allem was ich bisher rausgefunden habe müsste es sich also um SAML handeln, ...

Wenn ich das hier: https://www.onelogin.com/de-de/learn/saml
richtig verstehe, muss ich den SAML_Request, den ich schon empfangen habe Base64 Decodieren und dann "Validieren" und entsprechend wieder zurücksenden.
Dann mach ich mich mal an die Dekodierung, evtl wird dann auch erklärt wie die validierung geht ;)
--
Just try it

Warf
Beiträge: 1908
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Wie macht man Single Sign On mit FPC ?

Beitrag von Warf »

SAML ist eine Identifizierungsschnittstelle auf XML Basis.

Im grunde läuft das so ab, um eine SAML anfrage zu senden, schickst du den Nutzer auf eine Website mit den Anfragenparametern in der URL encoded. Der nutzer macht dann auf dieser website was auch immer benötigt wird um sich anzumelden (ist dir komplett egal, das ist eine komplett separate website), und wenn der Nutzer fertig ist sendet der SAML server den nutzer per redirect zurück zu deiner Anwendung, mit der SAML antwort entweder als URL Parameter, oder als POST Request body.

Die implementierung ist also relativ einfach:
1. Du rufst den Standardbrowser des Nutzers auf mit dem SAML Request in der Addresse zum SAML server.
2. Du startest einen lokalen webserver auf den der Browser dann den Rücksprung ausführen kann
3. Wenn der Rücksprung passiert, liest die die sAML antwort aus und validierst sie (xml parsen, signaturen prüfen, etc.)
4. Du kannst den webserver wieder runterfahren und mit der SAML antwort machen was du möchtest

Benutzeravatar
corpsman
Lazarusforum e. V.
Beiträge: 1496
Registriert: Sa 28. Feb 2009, 08:54
OS, Lazarus, FPC: Linux Mint Mate, Lazarus GIT Head, FPC 3.0
CPU-Target: 64Bit
Wohnort: Stuttgart
Kontaktdaten:

Re: Wie macht man Single Sign On mit FPC ?

Beitrag von corpsman »

*g*,
Die SAML_Request die ich im 1. Post geschwärtzt hatte konnte ich mittlerweile Base64 Dekodieren und ja, da kam eine XML Datei raus. Mir war auch schon aufgefallen, dass die Antwort die meine Anwendung dann Senden muss "Länger" ist. Nun ist auch klar warum. Verstehe ich dich RIchtig, dass diese Statisch ist und ich sobald ich diese Antwort einmal habe diese "dauerhaft" verwenden kann ?

Dieses Vorgehen würde dann mir helfen, eine Lösung die auch die Kollegen nutzen können, kriege ich evtl raus, wenn ich verstanden habe wie ich die XML Informationen in die benötigte Antwort umwandeln kann..

Mal sehen wann wieder ne Mittagspause ist, in der ich mir das ansehen kann, danke auf jeden Fall für die Übersicht..
--
Just try it

Warf
Beiträge: 1908
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Wie macht man Single Sign On mit FPC ?

Beitrag von Warf »

Es kommt ein bisschen drauf an was in der SAML antwort drin ist. Bei einem SSO System bekommst du normalerweise irgendeine Form des Token (evtl sogar die komplette SAML assertion selbst ist das token), die du dann über eine gewisse lebenszeit hinweg benutzen kannst um dich als der Nutzer auszuweisen dessen login dieses Token erzeugt hat.

Wie lang das gültig ist kommt auf das Token an, kann ein paar Minuten, Stunden oder sogar Tage bis Monate sein.

Benutzeravatar
corpsman
Lazarusforum e. V.
Beiträge: 1496
Registriert: Sa 28. Feb 2009, 08:54
OS, Lazarus, FPC: Linux Mint Mate, Lazarus GIT Head, FPC 3.0
CPU-Target: 64Bit
Wohnort: Stuttgart
Kontaktdaten:

Re: Wie macht man Single Sign On mit FPC ?

Beitrag von corpsman »

Sry hat ein bisschen gedauert.

ich hab mal "Man in the Middle" gespielt und die Base64 Codierten Nachrichten Dekodiert und zur Veröffentlichung bereinigt, auf dass wir ne Grundlage zum "Betrachten" haben.

Die Request die der SSO Server mir schickt konnte ich Problemlos dekodieren und ergibt sich dann zu folgender XML-Datei:

Code: Alles auswählen


<?xml version="1.0" encoding="UTF-8"?>
<saml2p:AuthnRequest xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" AssertionConsumerServiceURL="https://../saml/SSO" Destination="https://URL" ForceAuthn="false" ID="ID" IsPassive="false" IssueInstant="2023-02-03T12:32:46.746Z" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Version="2.0">
  <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">eid</saml2:Issuer>
  <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
    <ds:SignedInfo>
      <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
      <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
      <ds:Reference URI="URI">
        <ds:Transforms>
          <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
          <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
        </ds:Transforms>
        <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
        <ds:DigestValue>digest</ds:DigestValue>
      </ds:Reference>
    </ds:SignedInfo>
    <ds:SignatureValue>Signatur</ds:SignatureValue>
    <ds:KeyInfo>
      <ds:X509Data>
        <ds:X509Certificate>Certificat</ds:X509Certificate>
      </ds:X509Data>
    </ds:KeyInfo>
  </ds:Signature>
  <saml2p:NameIDPolicy Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"/>
</saml2p:AuthnRequest>
Ich habe dann eine "Antwort" die der FF generiert hatte mit geschnitten und versucht ebenfalls Base64 zu dekodieren:

Code: Alles auswählen


<samlp:Response ID="ID" Version="2.0" IssueInstant="2023-02-06T06:32:41.788Z" Destination="https://../saml/SSO" Consent="urn:oasis:names:tc:SAML:2.0:consent:unspecified" InResponseTo="ID" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol
"Kauderwelsch, verschlüsselt, nicht lesbar ??"
<xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc" 
"Kauderwelsch, verschlüsselt, nicht lesbar ??"
<ds:X509IssuerName>CN=, OU=, O=, L=Unknown, S=Unknown, C=DE</ds:X509IssuerName>
<ds:X509SerialNumber>12345</ds:X509SerialNumber>
</ds:X509IssuerSerial6
"Kauderwelsch, verschlüsselt, nicht lesbar ??"
Auffällig ist, dass immer wieder "Blöcke" drin sind die der Base64 decoder nicht dekodieren konnte ich hab das mit "Kauderwelsch, verschlüsselt, nicht lesbar ??" markiert, kann es sein das die base64 Unit von FPC da noch nicht vollständig ist ?

Die Nächsten Herausforderungen für mich sind also, raus kriegen wie ich aus dem ersten das zweite generieren kann, über jedweden Input und oder Abkürzungen drum rum freue ich mich .. ;)

[Edit]
Ok also erste Erkenntniss, der Base64 Decoder kommt "durcheinander", weil im Datenstrom ungültige Zeichen sind:

Code: Alles auswählen

%2BPHNhbWxwOlN0YXR1cz48c2FtbHA6U3Rhd
das % Zeichen darf da natürlich nicht drin stehen, ich denke das kommt daher, dass es ja eigentlich eingebetttet ist in eine HTML-Nachricht und das %2B wahrscheinlich in dem HTML nicht erlaubt ist, nun muss ich also raus kriegen wie meinen Base64 String erst umwandeln muss, dass der hier bereinigt ist ..
Zuletzt geändert von corpsman am Mi 8. Feb 2023, 10:22, insgesamt 1-mal geändert.
--
Just try it

Socke
Lazarusforum e. V.
Beiträge: 3158
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: Wie macht man Single Sign On mit FPC ?

Beitrag von Socke »

corpsman hat geschrieben:
Mi 8. Feb 2023, 10:10
Ich habe dann eine "Antwort" die der FF generiert hatte mit geschnitten und versucht ebenfalls Base64 zu dekodieren:

Code: Alles auswählen


<samlp:Response ID="ID" Version="2.0" IssueInstant="2023-02-06T06:32:41.788Z" Destination="https://../saml/SSO" Consent="urn:oasis:names:tc:SAML:2.0:consent:unspecified" InResponseTo="ID" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol
"Kauderwelsch, verschlüsselt, nicht lesbar ??"
<xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc" 
"Kauderwelsch, verschlüsselt, nicht lesbar ??"
<ds:X509IssuerName>CN=, OU=, O=, L=Unknown, S=Unknown, C=DE</ds:X509IssuerName>
<ds:X509SerialNumber>12345</ds:X509SerialNumber>
</ds:X509IssuerSerial6
"Kauderwelsch, verschlüsselt, nicht lesbar ??"
Auffällig ist, dass immer wieder "Blöcke" drin sind die der Base64 decoder nicht dekodieren konnte ich hab das mit "Kauderwelsch, verschlüsselt, nicht lesbar ??" markiert, kann es sein das die base64 Unit von FPC da noch nicht vollständig ist ?
Das Base64 ist schon korrekt implementiert. Du versuchst nur Binärdaten zu dekodieren ;-). Das SAML 2.0 Protokoll ist kryptografisch gesichert. Die Signaturen (oder ggf. auftretenden öffentlichen Schlüssel) sind zur Übertragung Base64 kodiert.

Die SAML 2.0 Service Provider, die ich kenne (SAP), nutzen zwei Schlüsselpare, jeweils eines zum Signieren und eines zum Verschlüsseln. Was dann aber genau genutzt wird weiß ich nicht.

Wenn deine Anwendung eine Anmelde-Antwort erhält, musst du du dort enthaltenen Signaturen gegen lokal bei dir gespeicherte Zertifikate des Identity Providers validieren. Ansonsten ergibt die Kryptografie darin keinen Sinn.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Benutzeravatar
theo
Beiträge: 10467
Registriert: Mo 11. Sep 2006, 19:01

Re: Wie macht man Single Sign On mit FPC ?

Beitrag von theo »

Vielleicht hilft es weiter, dem Link dort zu folgen?
https://www.w3.org/TR/2002/REC-xmlenc-c ... rview.html

Benutzeravatar
corpsman
Lazarusforum e. V.
Beiträge: 1496
Registriert: Sa 28. Feb 2009, 08:54
OS, Lazarus, FPC: Linux Mint Mate, Lazarus GIT Head, FPC 3.0
CPU-Target: 64Bit
Wohnort: Stuttgart
Kontaktdaten:

Re: Wie macht man Single Sign On mit FPC ?

Beitrag von corpsman »

Sodale:
also die Responce wird ja Uri encoded, damit ich das Lesen kann muss ich es vorher UriDecoden, wenn man das macht kommt ein 1a XML heraus:

Code: Alles auswählen

<samlp:Response ID="" Version="2.0" IssueInstant="2023-02-08T09:13:02.212Z" Destination="https://../saml/SSO" Consent="urn:oasis:names:tc:SAML:2.0:consent:unspecified" InResponseTo="ID" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol">
  <Issuer xmlns="urn:oasis:names:tc:SAML:2.0:assertion">https://idp/trust</Issuer>
  <samlp:Status>
    <samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
  </samlp:Status>
  <EncryptedAssertion xmlns="urn:oasis:names:tc:SAML:2.0:assertion">
    <xenc:EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
      <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc"/>
      <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
        <e:EncryptedKey xmlns:e="http://www.w3.org/2001/04/xmlenc#">
          <e:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p">
            <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
          </e:EncryptionMethod>
          <KeyInfo>
            <ds:X509Data xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
              <ds:X509IssuerSerial>
                <ds:X509IssuerName>CN=, OU=, O=, L=Unknown, S=Unknown, C=DE</ds:X509IssuerName>
                <ds:X509SerialNumber>1234</ds:X509SerialNumber>
              </ds:X509IssuerSerial>
            </ds:X509Data>
          </KeyInfo>
          <e:CipherData>
            <e:CipherValue>Data</e:CipherValue>
          </e:CipherData>
        </e:EncryptedKey>
      </KeyInfo>
      <xenc:CipherData>
        <xenc:CipherValue>Value</xenc:CipherValue>
      </xenc:CipherData>
    </xenc:EncryptedData>
  </EncryptedAssertion>
</samlp:Response>
Damit muss ich nun verstehen wie ich aus dem ersten XML das 2. machen kann ;)
--
Just try it

Antworten