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:
- In welchen Arten von Anwendungen wird es verwendet?
- Wie lange ist es gültig?
- 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?
- Es geht um eine public API, für eine App wäre Basic Auth durchaus machbar, im Browser eher ungünstig
- Benutzername und Passwort sind so lange verwendbar, bis sie geändert werden.
- 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