diff --git a/lib/Travelynx/Helper/Traewelling.pm b/lib/Travelynx/Helper/Traewelling.pm
index 1b94aa0c2af7dbff9556d0edbb2978c5a435956d..6d7c3672e8f642742a6c62d04dead2b80e7c454d 100644
--- a/lib/Travelynx/Helper/Traewelling.pm
+++ b/lib/Travelynx/Helper/Traewelling.pm
@@ -4,6 +4,8 @@ use strict;
 use warnings;
 use 5.020;
 
+use DateTime;
+use DateTime::Format::Strptime;
 use Mojo::Promise;
 
 sub new {
@@ -182,10 +184,16 @@ sub login_p {
 			}
 			else {
 				$token = $tx->result->json->{token};
+
+               # As of 2020-10-04, Traewelling tokens expire one year after they
+               # are generated
+				my $expiry_dt = DateTime->now( time_zone => 'Europe/Berlin' )
+				  ->add( years => 1 );
 				$self->{model}->link(
-					uid   => $uid,
-					email => $email,
-					token => $token
+					uid     => $uid,
+					email   => $email,
+					token   => $token,
+					expires => $expiry_dt
 				);
 				return $self->get_user_p( $uid, $token );
 			}
diff --git a/lib/Travelynx/Model/Traewelling.pm b/lib/Travelynx/Model/Traewelling.pm
index 1a2f4ec039185f48c9276f0579c23a67b133c022..c9b2181b1f43d9ab0e681c89b2957f2f1212ec7b 100644
--- a/lib/Travelynx/Model/Traewelling.pm
+++ b/lib/Travelynx/Model/Traewelling.pm
@@ -37,24 +37,29 @@ sub link {
 	my $log = [ [ $self->now->epoch, "Erfolgreich angemeldet" ] ];
 
 	my $data = {
+		log     => $log,
+		expires => $opt{expires}->epoch,
+	};
+
+	my $user_entry = {
 		user_id   => $opt{uid},
 		email     => $opt{email},
 		push_sync => 0,
 		pull_sync => 0,
 		token     => $opt{token},
-		data      => JSON->new->encode( { log => $log } ),
+		data      => JSON->new->encode($data),
 	};
 
 	$self->{pg}->db->insert(
 		'traewelling',
-		$data,
+		$user_entry,
 		{
 			on_conflict => \
 '(user_id) do update set email = EXCLUDED.email, token = EXCLUDED.token, push_sync = false, pull_sync = false, data = null, errored = false, latest_run = null'
 		}
 	);
 
-	return $data;
+	return $user_entry;
 }
 
 sub set_user {
@@ -96,6 +101,16 @@ sub get {
 	for my $log_entry ( @{ $res_h->{data}{log} // [] } ) {
 		$log_entry->[0] = epoch_to_dt( $log_entry->[0] );
 	}
+	$res_h->{expires_on} = epoch_to_dt( $res_h->{data}{expires} );
+
+	my $expires_in = ( $res_h->{data}{expires} // 0 ) - $self->now->epoch;
+
+	if ( $expires_in < 0 ) {
+		$res_h->{expired} = 1;
+	}
+	elsif ( $expires_in < 14 * 24 * 3600 ) {
+		$res_h->{expiring} = 1;
+	}
 
 	return $res_h;
 }
diff --git a/templates/account.html.ep b/templates/account.html.ep
index 093049c3a4efbf0ab9ef94b9527d967a060f0f22..e5220eed029a61882879fa3ed43084177ac60ea5 100644
--- a/templates/account.html.ep
+++ b/templates/account.html.ep
@@ -17,7 +17,7 @@
 						<span class="card-title">Einstellungen zu öffentlichen Account-Daten geändert</span>
 					% }
 					% elsif ($success eq 'traewelling') {
-						<span class="card-title">Traewelling-Verknüpfung aktualisiert</span>
+						<span class="card-title">Träwelling-Verknüpfung aktualisiert</span>
 					% }
 					% elsif ($success eq 'use_history') {
 						<span class="card-title">Einstellungen zu vorgeschlagenen Verbindungen geändert</span>
@@ -123,11 +123,17 @@
 						<span style="color: #999999;">Nicht verknüpft</span>
 					% }
 					% elsif ($traewelling->{errored}) {
-						Fehlerhaft <i class="material-icons">error</i>
+						Fehlerhaft <i class="material-icons" aria-hidden="true">error</i>
 					% }
 					% else {
 						Verknüpft mit <%= $traewelling->{data}{user_name} // $traewelling->{email} %>
-						% if ($traewelling->{pull_sync}) {
+						% if ($traewelling->{expired}) {
+							– Login-Token abgelaufen <i class="material-icons" aria-hidden="true">error</i>
+						% }
+						% elsif ($traewelling->{expiring}) {
+							– Login-Token läuft bald ab <i class="material-icons" aria-hidden="true">warning</i>
+						% }
+						% elsif ($traewelling->{pull_sync}) {
 							– Checkins in Träwelling werden von travelynx übernommen
 						% }
 						% elsif ($traewelling->{push_sync}) {
diff --git a/templates/traewelling.html.ep b/templates/traewelling.html.ep
index d4e4ffdc15f1f58bb24380ce4b23764946f9bbb9..acac9fa4037c3f6243c1bb34085e04841c3ff08f 100644
--- a/templates/traewelling.html.ep
+++ b/templates/traewelling.html.ep
@@ -117,7 +117,7 @@
 				% else {
 					%= $traewelling->{email}
 				% }
-				verknüpft.
+				verknüpft. Der Login-Token läuft <%= $traewelling->{expires_on}->strftime('am %d.%m.%Y um %H:%M Uhr') %> ab.
 			</p>
 		</div>
 	</div>