Authentifizierung App > Backend

OnDemand

Top Contributor
Hi!

ich versuche grad einen Überblick zu bekommen, wie ich die Backend API am einfachsten absichere. Meine erste und einfachste Lösung wäre, dass man in der Webapp einen Token einmalig generiert und nur einmalig anzeigt, welchen man in der Android-App abspeichert. Mit diesem Token authentifiziert sich die Android App am Backend. Was spricht dagegen? Wie speichere ich den Token am sichersten in der Android App ab?

Vielen Dank für eure Ideen und Unterstützung
 

KonradN

Super-Moderator
Mitarbeiter
Erster Hinweis: generiere da nichts selbst. Da gibt es fertige Lösungen.
Und so ein Token kann man in Android gut als Shared Preference abspeichern.

Siehe z.B. folgendes:
 

OnDemand

Top Contributor
Sieht irgendwie kompliziert aus. Jeder User, kann sich mit seiner Mobile App auf die eigene Instanz seiner Webapp verbinden. Ich habe also nicht eine einzige Webapp, an die sich mehrere Android Apps hängen, sondern 1 Android App zu 1 Webapp.

Hab mir mal ein paar andere Systeme angesehen wie die das machen. Ein großer Shopsystemhersteller zb erstellt einen Token. Dieser wird einmal angezeigt.

Dieser Token muss dann in jedem RequestHeader (https only) angegeben werden um sich zu authentifizieren. Ist doch ziehmlich einfach oder übersehe ich da was? Wo sind da die Risiken?
 

mihe7

Top Contributor
Dann trete ich mal der Diskussion bei, Sicherheit ist ja ein Thema, das uns alle etwas angeht. Das Folgende stellt lediglich meine laienhaften Überlegungen zur Schau, die gerne ergänzt/korrigiert werden können.

Immer davon ausgehend, dass TLS verwendet wird, kommt das auf das Token an. Spontan fallen mir folgende Fragen ein:
  1. In welchen Arten von Anwendungen wird es verwendet?
  2. Wie lange ist es gültig?
  3. Wie und wozu wird es ausgewertet?
Machen wir mal den einfachsten Fall: Du legst einen Benutzer mit Passwort an, der nur die API aufrufen und dabei - wichtig - sein Passwort nicht selbst ändern kann und verwendest HTTP Basic Authentication.

Was mir fällt mir dazu ein?
  1. Es geht um eine public API, für eine App wäre Basic Auth durchaus machbar, im Browser eher ungünstig
  2. Benutzername und Passwort sind so lange verwendbar, bis sie geändert werden.
  3. Es erfolgen Zugriffe auf die DB/externes System, auch der Autorisierung wegen.
Jetzt könnte ich ein Token z. B. aus Benutzername und Passwort generieren (und beim Benutzer hinterlegen), das bei jedem Request im Header mitgeschickt wird. Wo ist der Unterschied? Gut, damit ich aus JS nicht darauf zugreifen kann, müsste ich einen Http-Only-Cookie verwenden. Rein technisch betrachtet, ist es halt einfach ein anderer HTTP-Header. Zumindest im Browser wäre das angenehmer.

Kommen Credentials/Token "abhanden", kann man neue vergeben. Deswegen ist es auch wichtig, dass der API-User sein Passwort nicht selbst ändern kann. Jemand, der die Zugangsdaten hat, könnte sie sonst ändern und den legitimen User aussperren.

Kurz: der Unterschied zwischen einem Token und den Credentials ist in diesem Fall praktisch nicht gegeben, weil man Benutzername und Passwort als Token auffassen kann.

Der nächste Schritt: Sessions. Man tauscht ein Token/Credentials gegen ein anderes Token, das nur für eine Sitzung gilt -> sprich: ein Session-Cookie. Was bringt das? Naja, die Session kann gecached werden, so dass ich zunächst keinen Zugriff auf ein anderes System benötige. Außer... ich habe es mit mehreren Instanzen des Backends zu tun, dann müsste ich entweder Sticky Sessions im LoadBalancer konfigurieren oder einen verteilten Session Cache verwenden.

Der nächste Schritt: JWT. Statt eines praktisch zufälligen Tokens wird hier ein Token verwendet, das die benötigten Angaben zum Benutzer und seinen Rollen gleich mitbringt. Auf REST-Seite muss somit nicht mehr auf externe Systeme zugegriffen werden, wenn (und nur wenn) das Token digital signiert ist. Nachteil: ein einmal ausgegebenes Token kann nicht zurückgezogen werden - zumindest, wenn man nicht wieder Zustand managen möchte.

Deswegen verwendet man für nicht vertrauenswürde Clients zwei Tokens: ein kurzlebiges Access-Token und ein langlebiges Refresh-Token. Die Rest-API arbeitet nur mit dem Access-Token. Das Refresh-Token dient der Ausstellung neuer Access-Tokens. Bei der Gelegenheit kann natürlich die Gültigkeit überprüft werden. Kommt das Access-Token abhanden -> Pech gehabt. Kommt das Refresh-Token abhanden, lässt sich das alte sperren, so dass keine neuen Access-Tokens ausgestellt werden können.

Das sind jetzt nur mal ein paar Überlegungen. Das Thema ist äußerst komplex, es dauert schon, bis man alleine OAuth 2 und Open ID Connect halbwegs verstanden hat und selbst die Experten, die an diesen Standards mitarbeiten, haben ihre liebe Mühe, immer alle Konsequenzen zu berücksichtigen. Daher ist es auch wichtig, da nichts selbst entwickeln zu wollen. Es greifen einfach viel zu viele Rädchen ineinander und an praktisch jeder Stelle reicht ein kleiner (Gedanken-/Implementierungs-)Fehler und schon ist die Sicherheit hinüber.

Auf dem Client gilt: alles, was dort landet, ist unsicher, oder anders gesagt: man kann es Angreifern immer nur möglichst schwer machen aber 100-%ige Sicherheit gibt es nicht. Ob SharedPreferences alleine reichen, muss man selbst entscheiden. Man könnte die Tokens vor dem Speichern noch verschlüsseln, dann kann man die auch auf einem gerooteten Gerät nicht einfach auslesen. Und, ich merke, man muss aufpassen, dass man beim Thema Sicherheit nicht paranoid wird :p
 

OnDemand

Top Contributor
Vielen lieben Dank für deinen Input.!

An JWT bin ich erstmal gescheitert da brauch ich mehr Zeit. Zum android entwickeln lernen hab ich in der Serveranwendung nun erstmal Basic eingebaut. Via https natürlich.

Aktuell nehme ich da die selben Logindateb wie in der weboberfläche. Also der Benutzer logged sich mit der App genau so ein wie über den Browser. Vermutlich nicht die beste Idee? Für meine Übung aber erstmal ok.

Wie könnte man Basic noch sicherer machen? Wie sicher ist überhaupt nötigt?
Die App ruft Daten vom Server wie Adressaten von seinen Kunden, sensibler wird es nicht. Die könnte man ja auch zusätzlich verschlüsseln für den Transport?

Welche Alternativen gibts noch? Oauth ist ganz schön komplex
 

KonradN

Super-Moderator
Mitarbeiter
Aktuell nehme ich da die selben Logindateb wie in der weboberfläche. Also der Benutzer logged sich mit der App genau so ein wie über den Browser. Vermutlich nicht die beste Idee?
Das ist das, was üblich ist auch vom Anwender erwartet wird.

Wie könnte man Basic noch sicherer machen? Wie sicher ist überhaupt nötigt?
Dir wurden ja diverse Ideen genannt von @mihe7. Ich habe tatsächlich mal ein System gebaut, bei dem jedes System eine ID hatte (Firebase vergeben), die Anmeldung war nur einmalig und dann gab es eine Combo aus FirebaseId und generiertem Token, mit der der Client vieles machen konnte. (Kritische Dinge gab es da nicht - da hätte man aber noch einmal eine explizite Anmeldung fordern können.)

Sicherheit ist in der Regel nicht verhandelbar. Die Frage ist, was für ein Schaden entstehen kann. Das ist also nur ein einfaches Risiko-Management. Wenn Du da bei Fahrlässigkeit in den Knast gehen kannst oder da ein Konzern pleite gehen könnte, dann ist das etwas anderes, als wenn der Hacker dann ein paar Witze zu lesen bekommen kann. Bei mir war es unkritisch, daher konnte ich etwas "schlampen".

Welche Alternativen gibts noch? Oauth ist ganz schön komplex
OAUTH2 ist in sich zwar komplex, aber Du sollst das ja nur anwenden. Und da läuft es doch massiv auf eine Übernahme von Code aus Tutorials heraus. Und das Gute ist, dass Du darüber auch über viele Quellen autorisieren kannst, da dies von vielen angeboten wird. Und Du musst keine Nutzerverwaltung aufbauen - Identity Management Systeme gibt es genug, z.B. Keycloak.
 

mihe7

Top Contributor
Die könnte man ja auch zusätzlich verschlüsseln für den Transport?
Tust ja schon (https).

An JWT bin ich erstmal gescheitert da brauch ich mehr Zeit
Das kann ich gut nachvollziehen :)

Aktuell nehme ich da die selben Logindateb wie in der weboberfläche. Also der Benutzer logged sich mit der App genau so ein wie über den Browser. Vermutlich nicht die beste Idee?
Ich sehe das nicht allzu problematisch. Es geht ja schon damit los, wie groß das Interesse an einem (missbräuchlichen) Zugriff auf das System ist. Wenn Du ein global Player bist, Du viele unbekannte Nutzer hast oder der Schaden bei einem Fremdzugriff wirklich groß wäre, dann ist das natürlich etwas völlig anderes, als wenn Du für eine Nische ein B2B-Produkt hast oder für den Verein eine Mitgliederverwaltung aufsetzt.

Wenn die Benutzerdaten sicher oder gar nicht abgelegt werden, wüsste ich nicht, was daran problematischer als im Browser oder im E-Mail-Client sein sollte.

Ansonsten sind Benutzername und Passwort ja nicht per se unsicher, die ganze Welt arbeitet damit, so wie auch der Zugriff auf die Webapp darüber läuft. Es liegt halt ein gutes Stück weit in der Verantwortung des Users, ein entsprechend gutes und langes Passwort zu wählen (das kann man natürlich forcieren).

Wenn man wirklich etwas für die Sicherheit tun will, dann führt m. E. sowieso kein Weg an 2FA vorbei.

Wie könnte man Basic noch sicherer machen?

Wie gesagt:

1. TLS - hast Du ja schon.
2. Passwörter sicher oder gar nicht ablegen
3. Account verwenden, der sein PW nicht ändern kann (das kannst Du Dir auch sparen, wenn das PW z. B. von einem Admin des Kunden zurückgesetzt werden kann und im Webclient nicht mehr Funktionalität als auf der REST-API zur Verfügung steht)

Ansonsten wüsste ich nicht, was man da großartig sicherer machen könnte.
 

KonradN

Super-Moderator
Mitarbeiter
Ganz vergessen: paar Startpunkte bezüglich Andoid Apps un OAUTH:

Oder wenn Du bei Android einfach auf Google setzen willst:
(In der Regel haben die Leute auf Android ein Google Account. Die Gruppe der sehr bewussten Leute, die sowas meiden und dann gerootete Applikationen haben, ist sehr klein. Maximal noch Amazon Geräte - aber da hat man ggf. ein OAUTH von Amazon? Oder bieten die das nicht an? Habe ich noch nicht so drauf geachtet, aber wäre meine Erwartungshaltung, dass es das dort auch gibt.)
 

mihe7

Top Contributor
Für meine Begriffe liegt der Nutzen von OIDC/OAuth in erster Linie nicht in einer erhöhten Sicherheit, sondern

a) OAuth: die Autorisierung zwischen Services
b) OIDC: SSO.
c) durch JWT: Benutzerdaten/Rollen sind bereits enthalten, kein externer Zugriff mehr notwendig.

Das erkauft man sich durch ein komplexes System, bei dessen Verwendung man auch Fehler machen kann (z. B. nicht signierte JWTs, falsches Speichern von JWT-Tokens - weil, ist ja sicher - u. ä.)

Ich sehe das so, dass durch das System als solches neue (sicherheitsrelevante) Probleme entstehen, die durch noch mehr Komplexität gelöst werden müssen. Dazu muss man sich nur mal die Flows ansehen, wie umfangreich die z. T. sind. Auth Grant: Client kontaktiert Resource Server, Resource Server leitet um zum Authorization Server, der zeigt dem User eine Login-Maske an, der User authentisiert sich ggf. auch durch mehrere Faktoren, dann bekommt der Client einen Authorization Code, den muss der Client wieder beim Authorization Server gegen ein Access Token (und andere) tauschen, mit dem Access Token kann dann auf die API zugegriffen werden - bis zum Ablauf der Gültigkeit des Tokens. Also muss man die Gültigkeitsdauer kurz halten, dann braucht man aber ein Refresh Token, also gibts das auch noch dazu. Und das ist auch nur der grobe Ablauf. Im Hintergrund kommen noch weitere Dinge hinzu: der Auth-Code-Tausch ist "anfällig" für CSRF oder Injection, also bauen wir noch PKCE ein. Irgendwo gibts glaub ich noch ein Nonce wg. was weiß ich.

Wenn ich dann auch noch sehe, dass z. B. der Implicit Flow erst eine best practice für Apps und JS-Anwendungen war, mittlerweile davon abgeraten wird, dann erhöht das auch nicht gerade mein Vertrauen. Andererseits kann man mehr Authentifizierungsmerkmale einsetzen, die die Sicherheit natürlich schon erhöhen.

Nun setzt das auch alle Welt ein, insofern ist das sicher kein Problem aber ich frage mich schon, ob dieses ganze Zeug nicht allmählich so komplex wird, dass die Komplexität selbst zum Sicherheitsproblem wird.
 

wer112

Top Contributor
Erster Hinweis: generiere da nichts selbst. Da gibt es fertige Lösungen.
Und so ein Token kann man in Android gut als Shared Preference abspeichern.

Siehe z.B. folgendes:
Wenn er den Token einmalig abspeichern tut in ShaPref und den gleichen ist bei Firebase hinterlegt, denke ich würde es problematisch sein:
1. Sollte man die Daten löschen oder die App neu installieren, ist der Token in ShaPref ja gelöscht, muss man neu anmelden.
2. Datenschutz ist das eher problematisch, da man ja ein gerootes Handy haben kann, wo man zugriff zu den ShaPrefs hat und es einsehen kann.
Dann könnte man ja den Token analysieren und dann einen neuen Token generieren und den ersetzen und mit Glück, wird man als komplett, als andere Person eingeloggt. bzw. sogar als Admin. Sollten wenige Nutzer sein, würde das etwas länger dauern, um mit Glück auf ein gültigen Token zu erhalten.
 

Neue Themen


Oben