diff --git a/includes/login.php b/includes/login.php
new file mode 100644
index 0000000..830b8fe
--- /dev/null
+++ b/includes/login.php
@@ -0,0 +1,108 @@
+
+
+ – oder mit Benutzername/Passwort –
+ get_error_message() );
+ }
+
+ // Userinfo holen
+ $userinfo = authentik_get_userinfo( $tokens['access_token'] );
+ if ( is_wp_error( $userinfo ) || empty( $userinfo ) ) {
+ authentik_login_error( 'Benutzerinformationen konnten nicht abgerufen werden.' );
+ }
+
+ // User finden oder erstellen
+ $user = authentik_find_or_create_user( $userinfo );
+ if ( is_wp_error( $user ) ) {
+ authentik_login_error( $user->get_error_message() );
+ }
+
+ // Einloggen
+ wp_set_auth_cookie( $user->ID, true );
+ wp_set_current_user( $user->ID );
+ do_action( 'wp_login', $user->user_login, $user );
+
+ // Weiterleitung
+ $redirect = admin_url();
+ if ( ! user_can( $user->ID, 'manage_options' ) ) {
+ $redirect = home_url();
+ }
+
+ wp_redirect( $redirect );
+ exit;
+}
+
+function authentik_login_error( $message ) {
+ wp_redirect( wp_login_url() . '?authentik_error=' . urlencode( $message ) );
+ exit;
+}
+
+// Fehlermeldung anzeigen
+add_filter( 'login_message', 'authentik_show_login_message' );
+function authentik_show_login_message( $message ) {
+ if ( ! empty( $_GET['authentik_error'] ) ) {
+ $message .= '' . esc_html( urldecode( $_GET['authentik_error'] ) ) . '
';
+ }
+ return $message;
+}
+
+// Frontend: Verknüpfungs-Button für eingeloggte User (Shortcode)
+add_shortcode( 'authentik_link_account', 'authentik_link_account_shortcode' );
+function authentik_link_account_shortcode() {
+ if ( ! is_user_logged_in() ) return '';
+
+ $user = wp_get_current_user();
+ $subject = get_user_meta( $user->ID, 'authentik_subject', true );
+
+ ob_start();
+ if ( $subject ) {
+ echo '✓ Dein Konto ist mit Authentik verknüpft.
';
+ } else {
+ $url = authentik_build_login_url();
+ echo 'Konto mit Authentik verknüpfen';
+ }
+ return ob_get_clean();
+}
diff --git a/includes/oauth.php b/includes/oauth.php
new file mode 100644
index 0000000..851a7b0
--- /dev/null
+++ b/includes/oauth.php
@@ -0,0 +1,73 @@
+ 'code',
+ 'client_id' => $s['client_id'],
+ 'redirect_uri' => $s['redirect_uri'],
+ 'scope' => 'openid email profile',
+ 'state' => $state,
+ ];
+
+ return authentik_get_authorize_url() . '?' . http_build_query( $params );
+}
+
+function authentik_exchange_code( $code ) {
+ $s = authentik_get_settings();
+ $res = wp_remote_post( authentik_get_token_url(), [
+ 'timeout' => (int) $s['timeout'],
+ 'body' => [
+ 'grant_type' => 'authorization_code',
+ 'code' => $code,
+ 'redirect_uri' => $s['redirect_uri'],
+ 'client_id' => $s['client_id'],
+ 'client_secret' => $s['client_secret'],
+ ],
+ ] );
+
+ if ( is_wp_error( $res ) ) {
+ return new WP_Error( 'token_request_failed', $res->get_error_message() );
+ }
+
+ $body = json_decode( wp_remote_retrieve_body( $res ), true );
+ if ( empty( $body['access_token'] ) ) {
+ return new WP_Error( 'token_missing', 'Kein Access-Token erhalten.' );
+ }
+
+ return $body;
+}
+
+function authentik_get_userinfo( $access_token ) {
+ $s = authentik_get_settings();
+ $res = wp_remote_get( authentik_get_userinfo_url(), [
+ 'timeout' => (int) $s['timeout'],
+ 'headers' => [ 'Authorization' => 'Bearer ' . $access_token ],
+ ] );
+
+ if ( is_wp_error( $res ) ) {
+ return new WP_Error( 'userinfo_failed', $res->get_error_message() );
+ }
+
+ return json_decode( wp_remote_retrieve_body( $res ), true );
+}
diff --git a/includes/settings.php b/includes/settings.php
new file mode 100644
index 0000000..9cb07d1
--- /dev/null
+++ b/includes/settings.php
@@ -0,0 +1,204 @@
+ '',
+ 'client_secret' => '',
+ 'discovery_url' => '',
+ 'redirect_uri' => admin_url( 'admin-ajax.php?action=authentik_callback' ),
+ 'default_role' => 'subscriber',
+ 'admin_group' => 'wordpress_admin',
+ 'timeout' => 30,
+ 'create_users' => 1,
+ 'link_existing' => 1,
+ 'sync_roles' => 1,
+ ];
+ $saved = get_option( 'authentik_settings', [] );
+ return wp_parse_args( $saved, $defaults );
+}
+
+function authentik_settings_page() {
+ $s = authentik_get_settings();
+ ?>
+
+
Authentik Login – Einstellungen
+
+ 15 ] );
+ if ( ! is_wp_error( $res ) ) {
+ $data = json_decode( wp_remote_retrieve_body( $res ), true );
+ if ( $data ) {
+ $map = [
+ 'authorization_endpoint' => 'authorize_url',
+ 'token_endpoint' => 'token_url',
+ 'userinfo_endpoint' => 'userinfo_url',
+ 'jwks_uri' => 'jwks_url',
+ 'issuer' => 'issuer',
+ 'end_session_endpoint' => 'logout_url',
+ ];
+ foreach ( $map as $key => $opt ) {
+ if ( isset( $data[ $key ] ) ) {
+ update_option( 'authentik_oidc_' . $opt, $data[ $key ] );
+ }
+ }
+ echo '
Discovery-Dokument erfolgreich importiert!
';
+ }
+ } else {
+ echo '
Fehler: ' . esc_html( $res->get_error_message() ) . '
';
+ }
+ }
+ ?>
+
+
+
+
+
+ ID, 'authentik_subject', $subject );
+ }
+ }
+
+ // 3. Verknüpfe bestehenden User per Benutzername
+ if ( ! $user && $s['link_existing'] && $username ) {
+ $user = get_user_by( 'login', $username );
+ if ( $user ) {
+ update_user_meta( $user->ID, 'authentik_subject', $subject );
+ }
+ }
+
+ // 4. Neuen User erstellen
+ if ( ! $user ) {
+ if ( ! $s['create_users'] ) {
+ return new WP_Error( 'user_not_found', 'Kein passender WordPress-Account gefunden.' );
+ }
+
+ $user_login = sanitize_user( $username ?: explode( '@', $email )[0] );
+ // Sicherstellen dass Benutzername einzigartig ist
+ if ( username_exists( $user_login ) ) {
+ $user_login = $user_login . '_' . substr( $subject, 0, 6 );
+ }
+
+ $user_id = wp_insert_user( [
+ 'user_login' => $user_login,
+ 'user_email' => $email,
+ 'user_pass' => wp_generate_password( 32 ),
+ 'display_name' => $userinfo['name'] ?? $user_login,
+ 'role' => $s['default_role'],
+ ] );
+
+ if ( is_wp_error( $user_id ) ) {
+ return $user_id;
+ }
+
+ update_user_meta( $user_id, 'authentik_subject', $subject );
+ $user = get_user_by( 'ID', $user_id );
+ }
+
+ // 5. Rollen synchronisieren
+ if ( $s['sync_roles'] && $user ) {
+ authentik_sync_roles( $user, $groups, $s );
+ }
+
+ return $user;
+}
+
+function authentik_find_user_by_subject( $subject ) {
+ $users = get_users( [
+ 'meta_key' => 'authentik_subject',
+ 'meta_value' => $subject,
+ 'number' => 1,
+ ] );
+ return ! empty( $users ) ? $users[0] : null;
+}
+
+function authentik_sync_roles( $user, $groups, $s ) {
+ $admin_group = $s['admin_group'];
+
+ if ( $admin_group && in_array( $admin_group, $groups, true ) ) {
+ $user->set_role( 'administrator' );
+ } else {
+ // Mappe Authentik-Gruppen auf WordPress-Rollen
+ $role_map = [
+ 'wordpress_editor' => 'editor',
+ 'wordpress_author' => 'author',
+ 'wordpress_contributor' => 'contributor',
+ 'wordpress_subscriber' => 'subscriber',
+ ];
+
+ $assigned = false;
+ foreach ( $role_map as $group => $role ) {
+ if ( in_array( $group, $groups, true ) ) {
+ $user->set_role( $role );
+ $assigned = true;
+ break;
+ }
+ }
+
+ if ( ! $assigned ) {
+ // Behalte aktuelle Rolle wenn keine Gruppe passt
+ }
+ }
+}
+
+// Profilseite: Verknüpfungsstatus anzeigen
+add_action( 'show_user_profile', 'authentik_show_link_status' );
+add_action( 'edit_user_profile', 'authentik_show_link_status' );
+function authentik_show_link_status( $user ) {
+ $subject = get_user_meta( $user->ID, 'authentik_subject', true );
+ ?>
+ Authentik-Verknüpfung
+
+