| | |
| | | import com.sun.net.httpserver.HttpExchange; |
| | | import com.sun.net.httpserver.HttpPrincipal; |
| | | import de.uhilger.httpserver.auth.realm.Realm; |
| | | import de.uhilger.httpserver.base.handler.HttpResponder; |
| | | import de.uhilger.httpserver.base.HttpResponder; |
| | | import io.jsonwebtoken.Claims; |
| | | import io.jsonwebtoken.JwtException; |
| | | import io.jsonwebtoken.Jwts; |
| | |
| | | |
| | | /** |
| | | * Die Klasse Authenticator authentifziert gemäß OAuth-Spezifikation |
| | | * |
| | | * |
| | | * "The OAuth 2.0 Authorization Framework: Bearer Token Usage" |
| | | * https://datatracker.ietf.org/doc/html/rfc6750 |
| | | * |
| | | * |
| | | * weitere Info-Links |
| | | * https://www.oauth.com/oauth2-servers/making-authenticated-requests/refreshing-an-access-token/ |
| | | * https://swagger.io/docs/specification/authentication/bearer-authentication/ |
| | | * |
| | |
| | | * @param password das Kennwort des Benutzers |
| | | * @return Token oder null, wenn die Anmeldung misslang |
| | | */ |
| | | public LoginResponse login(String userId, String password) { |
| | | public LoginResponse login(HttpExchange e, String userId, String password) { |
| | | if (realm.isValid(userId, password)) { |
| | | logger.info(userId + " logged in from IP." + e.getRemoteAddress()); |
| | | LoginResponse r = new LoginResponse(); |
| | | String token = createToken(userId, expireSeconds); |
| | | r.setToken(token); |
| | |
| | | r.setExpiresIn(expireSeconds); |
| | | return r; |
| | | } else { |
| | | logger.info("Invalid log in attempt for " + userId + " from IP " + e.getRemoteAddress()); |
| | | return null; |
| | | } |
| | | } |
| | |
| | | if(parts != null && parts.length > 1) { |
| | | token = parts[1].trim(); |
| | | } |
| | | } else { |
| | | // unschoen, aber fuer Image-Links in HTML-Inhalten |
| | | // mit Query versuchen |
| | | // z.B. |
| | | // GET /resource?access_token=mF_9.B5f-4.1JqM HTTP/1.1 |
| | | // Host: server.example.com |
| | | String query = exchange.getRequestURI().getQuery(); |
| | | if(query != null && query.toLowerCase().contains("access_token")) { |
| | | String[] parts = query.split("&"); |
| | | for(String part : parts) { |
| | | String[] keyVal = part.split("="); |
| | | if(keyVal[0].equalsIgnoreCase("access_token")) { |
| | | token = keyVal[1].trim(); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | return token; |
| | | } |
| | |
| | | * im WWW-Authenticate Header bestimmen |
| | | * |
| | | * @param exchange |
| | | * @return den Ausdruck fuer den WWW-Authenticate Header |
| | | */ |
| | | protected String getWWWAuthRealm(HttpExchange exchange) { |
| | | return wwwAuthRealm; |
| | |
| | | * WWW-Authenticate: Bearer realm="example" |
| | | * |
| | | * @param exchange |
| | | * @return |
| | | * @throws java.io.IOException |
| | | * @return das Ergebnis |
| | | */ |
| | | protected Result unauthorized(HttpExchange exchange) { |
| | | StringBuilder sb = new StringBuilder(); |
| | |
| | | return new Authenticator.Retry(SC_UNAUTHORIZED); |
| | | } |
| | | |
| | | /** |
| | | * Den Realm dieses Authenticators setzen |
| | | * @param realm der Realm |
| | | */ |
| | | public void setRealm(Realm realm) { |
| | | this.realm = realm; |
| | | } |
| | | |
| | | /** |
| | | * Pruefen, ob ein Nutzer eine Rolle hat |
| | | * @param userId die Kennung des Nutzers |
| | | * @param roleId die Rollen-ID des Nutzers |
| | | * @return true, wenn der Nutzer die Rolle hat, false wenn nicht |
| | | */ |
| | | public boolean hasRole(String userId, String roleId) { |
| | | return realm.hasRole(userId, roleId); |
| | | } |
| | | |
| | | /** |
| | | * Den Eintrag fuer das 'realm'-Attribut |
| | | * zur Nutzung im WWW-Authenticate Header setzen |
| | | * |
| | | * @param wwwAuthRealm der Text fuer das realm-Attribut im |
| | | * WWW-Autehnticate-Header |
| | | */ |
| | | public void setWWWAuthRealm(String wwwAuthRealm) { |
| | | this.wwwAuthRealm = wwwAuthRealm; |
| | | } |
| | | |
| | | /** |
| | | * Den Namen des Realms setzen, wie er fuer authentifizierte Benutzer |
| | | * vom Principal ausgegeben werden soll |
| | | * |
| | | * @param principalAuthRealm der Name des Realms fuer authentifizierte |
| | | * Benutzer |
| | | */ |
| | | public void setPrincipalAuthRealm(String principalAuthRealm) { |
| | | this.principalAuthRealm = principalAuthRealm; |
| | | } |
| | | |
| | | /** |
| | | * Die Dauer der Gueltigkeit einer Authentifizierung in Sekunden |
| | | * @param seconds die Sekunden, nach denen die Authentifizierung |
| | | * ungueltig wird |
| | | */ |
| | | public void setExpireSeconds(long seconds) { |
| | | this.expireSeconds = seconds; |
| | | } |
| | | |
| | | /** |
| | | * Die Dauer bis eine Authentifizierung eine Erneuerung benoetigt in Sekunden |
| | | * @param seconds die Sekunden, nach denen die Authentifizierung |
| | | * eine Erneuerung benoetigt |
| | | */ |
| | | public void setRefreshSeconds(long seconds) { |
| | | this.refreshSeconds = seconds; |
| | | } |
| | | |
| | | /** |
| | | * Die Dauer der Gueltigkeit eines Refresh-Token in Sekunden |
| | | * |
| | | * @param seconds die Anzhal Sekunden, die ein Refresh-Token gueltig ist |
| | | */ |
| | | public void setRefreshExpireSeconds(long seconds) { |
| | | this.refreshExpire = seconds; |
| | | } |