Files
SDL/VERAG_PROG_ALLGEMEIN/Schnittstellen/ATEZ/RELAYHUB/cRelayHubToken.vb
2026-10-06 09:24:20 +02:00

268 lines
12 KiB
VB.net

Imports System
Imports System.IO
Imports System.Net.Http
Imports System.Text
Imports System.Windows.Forms.VisualStyles.VisualStyleElement.StartPanel
Imports Newtonsoft.Json
Imports sun.security.util
Imports VERAG_PROG_ALLGEMEIN.cRelayHub
Public Class cRelayHubToken
Private Shared ReadOnly TOKEN_ENDPOINT_PROD As String = "https://login.singlewindow.io/auth/realms/agsw/protocol/openid-connect/token"
Private Shared ReadOnly TOKEN_ENDPOINT_TEST As String = "https://dev-kc.singlewindow.io/auth/realms/agsw/protocol/openid-connect/token"
Private Shared ReadOnly CLIENT_ID As String = "agsw-admin"
Private Shared ReadOnly USERNAME_PROD As String = "dhub@verag.ag"
Private Shared ReadOnly PASSWORD_PROD As String = "Dhub1234*"
Private Shared ReadOnly USERNAME_TEST As String = "andreas.test@test.com"
Private Shared ReadOnly PASSWORD_TEST As String = "Atez123."
Private Const ExpirySkewSeconds As Integer = 60
'======================================================================
' KONFIGURATION
'======================================================================
Private Shared Function GetTokenEndpoint(environment As cRelayHubEnvironment) As String
Select Case environment
Case cRelayHubEnvironment.TEST
Return TOKEN_ENDPOINT_TEST
Case cRelayHubEnvironment.PROD
Return TOKEN_ENDPOINT_PROD
Case Else
Throw New ApplicationException("Unbekannte RelayHub-Umgebung.")
End Select
End Function
Private Shared Function GetUsername(environment As cRelayHubEnvironment) As String
Select Case environment
Case cRelayHubEnvironment.TEST
Return USERNAME_TEST
Case cRelayHubEnvironment.PROD
Return USERNAME_PROD
Case Else
Throw New ApplicationException("Unbekannte RelayHub-Umgebung.")
End Select
End Function
Private Shared Function GetPassword(environment As cRelayHubEnvironment) As String
Select Case environment
Case cRelayHubEnvironment.TEST
Return PASSWORD_TEST
Case cRelayHubEnvironment.PROD
Return PASSWORD_PROD
Case Else
Throw New ApplicationException("Unbekannte RelayHub-Umgebung.")
End Select
End Function
Private Shared Function GetStorePath(environment As cRelayHubEnvironment) As String
Dim fileName As String = If(environment = cRelayHubEnvironment.TEST, "token_test.json", "token_prod.json")
Return Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.ApplicationData), "RelayHub", fileName)
End Function
'======================================================================
' ACCESS TOKEN
'======================================================================
Public Shared Function GetAccessToken(environment As cRelayHubEnvironment) As String
Dim store = LoadStore(environment)
If store IsNot Nothing AndAlso Not String.IsNullOrWhiteSpace(store.AccessToken) Then
If store.ExpiresAtUtc > DateTimeOffset.UtcNow.AddSeconds(ExpirySkewSeconds) Then Return store.AccessToken
End If
If store IsNot Nothing AndAlso Not String.IsNullOrWhiteSpace(store.RefreshToken) Then store = TryRefresh(store.RefreshToken, environment)
If store Is Nothing OrElse String.IsNullOrWhiteSpace(store.AccessToken) Then store = PasswordLogin(environment)
If store Is Nothing OrElse String.IsNullOrWhiteSpace(store.AccessToken) Then Throw New ApplicationException("Konnte keinen gültigen Access Token erhalten (" & environment.ToString() & ").")
SaveStore(store, environment)
Return store.AccessToken
End Function
'======================================================================
' LOGIN
'======================================================================
Private Shared Function PasswordLogin(environment As cRelayHubEnvironment) As TokenStore
Dim form = New Dictionary(Of String, String) From {
{"grant_type", "password"},
{"username", GetUsername(environment)},
{"password", GetPassword(environment)},
{"client_id", CLIENT_ID}
}
Dim resp = PostForm(form, environment)
Return ParseTokenResponse(resp, environment)
End Function
'======================================================================
' REFRESH
'======================================================================
Private Shared Function TryRefresh(refreshToken As String, environment As cRelayHubEnvironment) As TokenStore
Try
Dim form = New Dictionary(Of String, String) From {
{"grant_type", "refresh_token"},
{"refresh_token", refreshToken},
{"client_id", CLIENT_ID}
}
Dim resp = PostForm(form, environment)
Dim token = ParseTokenResponse(resp, environment)
If Not String.IsNullOrWhiteSpace(token.AccessToken) Then
SaveStore(token, environment)
Return token
End If
Catch ex As Exception
Console.WriteLine("Token Refresh fehlgeschlagen (" & environment.ToString() & "): " & ex.Message)
End Try
Return Nothing
End Function
'======================================================================
' HTTP
'======================================================================
Private Shared Function PostForm(formFields As Dictionary(Of String, String), environment As cRelayHubEnvironment) As String
Using client As New HttpClient()
Using content As New FormUrlEncodedContent(formFields)
Dim tokenEndpoint As String = GetTokenEndpoint(environment)
Dim username As String = GetUsername(environment)
Dim password As String = GetPassword(environment)
Console.WriteLine("")
Console.WriteLine("==================================================")
Console.WriteLine(" RELAYHUB TOKEN REQUEST")
Console.WriteLine("==================================================")
Console.WriteLine("Environment : " & environment.ToString())
Console.WriteLine("Token Endpoint : " & tokenEndpoint)
Console.WriteLine("Client ID : " & CLIENT_ID)
'Console.WriteLine("Username : " & username)
'Console.WriteLine("Password : " & password)
'Console.WriteLine("Password Länge : " & If(password Is Nothing, 0, password.Length))
'Console.WriteLine("Grant Type : " & If(formFields.ContainsKey("grant_type"), formFields("grant_type"), "<nicht gesetzt>"))
'Console.WriteLine("Token Store : " & GetStorePath(environment))
'Console.WriteLine("==================================================")
Dim response = client.PostAsync(tokenEndpoint, content).Result
Dim body = response.Content.ReadAsStringAsync().Result
If Not response.IsSuccessStatusCode Then Throw New ApplicationException("Token-Endpoint Fehler (" & environment.ToString() & " / " & CInt(response.StatusCode) & "): " & body)
Return body
End Using
End Using
End Function
'======================================================================
' TOKEN RESPONSE
'======================================================================
Private Shared Function ParseTokenResponse(json As String, environment As cRelayHubEnvironment) As TokenStore
Dim r = JsonConvert.DeserializeObject(Of TokenResponse)(json)
If r Is Nothing OrElse String.IsNullOrWhiteSpace(r.access_token) Then Throw New ApplicationException("Token-Antwort ungültig oder ohne access_token.")
Dim now = DateTimeOffset.UtcNow
Dim expiresIn = If(r.expires_in <= 0, 3600, r.expires_in)
Dim store = New TokenStore With {
.AccessToken = r.access_token.Trim(),
.RefreshToken = If(r.refresh_token, String.Empty),
.ExpiresAtUtc = now.AddSeconds(expiresIn)
}
Console.WriteLine("== Neuer RelayHub Token ==")
Console.WriteLine("Environment: " & environment.ToString())
Console.WriteLine("Gültig bis UTC: " & store.ExpiresAtUtc.ToString("yyyy-MM-dd HH:mm:ss"))
Return store
End Function
'======================================================================
' TOKEN LADEN
'======================================================================
Private Shared Function LoadStore(environment As cRelayHubEnvironment) As TokenStore
Try
Dim storePath As String = GetStorePath(environment)
If File.Exists(storePath) Then
Dim json = File.ReadAllText(storePath, Encoding.UTF8)
Dim s = JsonConvert.DeserializeObject(Of TokenStore)(json)
If s IsNot Nothing Then
Console.WriteLine("== Token aus Datei geladen ==")
Console.WriteLine("Environment: " & environment.ToString())
Console.WriteLine("Gültig bis UTC: " & s.ExpiresAtUtc.ToString("yyyy-MM-dd HH:mm:ss"))
End If
Return s
Else
Console.WriteLine("Keine Token-Datei für " & environment.ToString() & " vorhanden.")
End If
Catch ex As Exception
Console.WriteLine("Fehler beim Laden der Token-Datei: " & ex.Message)
End Try
Return Nothing
End Function
'======================================================================
' TOKEN SPEICHERN
'======================================================================
Private Shared Sub SaveStore(store As TokenStore, environment As cRelayHubEnvironment)
Try
Dim storePath As String = GetStorePath(environment)
Dim dir = Path.GetDirectoryName(storePath)
If Not Directory.Exists(dir) Then Directory.CreateDirectory(dir)
Dim json = JsonConvert.SerializeObject(store, Formatting.Indented)
File.WriteAllText(storePath, json, Encoding.UTF8)
Console.WriteLine("Token-Datei gespeichert: " & storePath)
Catch ex As Exception
Console.WriteLine("Fehler beim Speichern der Token-Datei: " & ex.Message)
End Try
End Sub
'======================================================================
' TOKEN LÖSCHEN
'======================================================================
Private Shared Sub Delete_Store(Optional environment As cRelayHubEnvironment = cRelayHubEnvironment.PROD)
Try
Dim storePath As String = GetStorePath(environment)
If File.Exists(storePath) Then File.Delete(storePath)
Console.WriteLine("Token-Datei gelöscht: " & storePath)
Catch ex As Exception
Console.WriteLine("Fehler beim Löschen der Token-Datei: " & ex.Message)
End Try
End Sub
Public Shared Sub DeleteAllStores()
Delete_Store(cRelayHubEnvironment.TEST)
Delete_Store(cRelayHubEnvironment.PROD)
End Sub
'======================================================================
' DTOs
'======================================================================
Private Class TokenResponse
Public Property access_token As String
Public Property expires_in As Integer
Public Property refresh_expires_in As Integer
Public Property refresh_token As String
Public Property token_type As String
Public Property scope As String
End Class
Private Class TokenStore
Public Property AccessToken As String
Public Property RefreshToken As String
Public Property ExpiresAtUtc As DateTimeOffset
End Class
End Class