No profiles configured. Create one to get started.
}
@foreach (var p in _profiles)
{
@p.Name
@p.TenantUrl
Tenant ID: @p.TenantId
Client ID: @p.ClientId
@if (Session.CurrentProfile?.Id == p.Id)
{
Active
}
}
@if (_showForm)
{
@(_editing?.Id == null ? "New Profile" : "Edit Profile")
@if (!string.IsNullOrEmpty(_formError))
{
@_formError
}
@* App registration section *@
Click "Register in Entra" to auto-create the app registration in the client tenant — requires Global Admin credentials.
Or enter an existing public client App Registration ID manually.
}
@code {
private List _profiles = new();
private bool _showForm;
private bool _registering;
private TenantProfile? _editing;
private TenantProfile _form = new();
private string _formError = string.Empty;
private string _pageError = string.Empty;
private bool CanRegister =>
!string.IsNullOrWhiteSpace(_form.Name) &&
!string.IsNullOrWhiteSpace(_form.TenantUrl) &&
!string.IsNullOrWhiteSpace(_form.TenantId);
protected override async Task OnInitializedAsync()
{
_profiles = (await ProfileRepo.LoadAsync()).ToList();
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (!firstRender) return;
await HandleRegResultAsync();
await HandleConnectErrorAsync();
}
private async Task HandleRegResultAsync()
{
var uri = new Uri(Nav.Uri);
var query = QueryHelpers.ParseQuery(uri.Query);
if (!query.TryGetValue("reg_result_key", out var key) || string.IsNullOrEmpty(key))
return;
var result = OAuthCache.GetAndRemoveRegistrationResult(key!);
if (result is not null)
{
_form = new TenantProfile
{
Name = result.TenantName,
TenantUrl = result.TenantUrl,
TenantId = result.TenantId,
ClientId = result.ClientId,
};
_showForm = true;
_formError = string.Empty;
await InvokeAsync(StateHasChanged);
}
Nav.NavigateTo(uri.GetLeftPart(UriPartial.Path), replace: true);
}
private async Task HandleConnectErrorAsync()
{
var uri = new Uri(Nav.Uri);
var query = QueryHelpers.ParseQuery(uri.Query);
if (!query.TryGetValue("connect_error", out var err) || string.IsNullOrEmpty(err))
return;
_pageError = err!;
await InvokeAsync(StateHasChanged);
Nav.NavigateTo(uri.GetLeftPart(UriPartial.Path), replace: true);
}
private void AddNew()
{
_editing = null;
_form = new TenantProfile();
_showForm = true;
_formError = string.Empty;
_pageError = string.Empty;
}
private void EditProfile(TenantProfile p)
{
_editing = p;
_form = new TenantProfile { Id = p.Id, Name = p.Name, TenantUrl = p.TenantUrl, TenantId = p.TenantId, ClientId = p.ClientId };
_showForm = true;
_formError = _pageError = string.Empty;
}
private void CancelForm() { _showForm = false; _editing = null; }
private void SelectProfile(TenantProfile p)
{
Session.SetProfile(p);
StateHasChanged();
}
private async Task RegisterAppAsync()
{
if (!CanRegister) return;
_registering = true;
StateHasChanged();
var returnUrl = Nav.Uri.Contains('?')
? Nav.Uri.Substring(0, Nav.Uri.IndexOf('?'))
: Nav.Uri;
var url = $"/connect/register-initiate" +
$"?tenantId={Uri.EscapeDataString(_form.TenantId)}" +
$"&tenantName={Uri.EscapeDataString(_form.Name)}" +
$"&tenantUrl={Uri.EscapeDataString(_form.TenantUrl)}" +
$"&returnUrl={Uri.EscapeDataString(returnUrl)}";
Nav.NavigateTo(url, forceLoad: true);
}
private async Task SaveProfile()
{
_formError = string.Empty;
if (string.IsNullOrWhiteSpace(_form.Name)) { _formError = "Name is required."; return; }
if (string.IsNullOrWhiteSpace(_form.TenantUrl)) { _formError = "Tenant URL is required."; return; }
if (string.IsNullOrWhiteSpace(_form.ClientId)) { _formError = "Client ID is required."; return; }
if (string.IsNullOrWhiteSpace(_form.TenantId)) { _formError = "Tenant ID is required."; return; }
if (_editing == null)
{
_form.Id = Guid.NewGuid().ToString();
_profiles.Add(_form);
}
else
{
var idx = _profiles.FindIndex(p => p.Id == _editing.Id);
if (idx >= 0) _profiles[idx] = _form;
}
await ProfileRepo.SaveAsync(_profiles);
_showForm = false; _editing = null;
}
private async Task DeleteProfile(TenantProfile p)
{
_profiles.RemoveAll(x => x.Id == p.Id);
await ProfileRepo.SaveAsync(_profiles);
if (Session.CurrentProfile?.Id == p.Id) await Session.ClearSessionAsync();
}
}