Skip to content

Commit

Permalink
+ (Core) Fixed Obsidian Login block issue where external authenticati…
Browse files Browse the repository at this point in the history
…on did not work with custom page routes. (Fixes #5641)
  • Loading branch information
joshuahenninger committed Oct 25, 2023
1 parent 9ba7e61 commit 3340780
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 7 deletions.
57 changes: 51 additions & 6 deletions Rock.Blocks/Security/Login.cs
Expand Up @@ -626,7 +626,9 @@ public BlockActionResult RemoteLoginStart( RemoteLoginStartRequestBag bag )
return ActionBadRequest( "Please try a different authentication method" );
}

var loginUrl = externalRedirectAuthentication.GenerateExternalLoginUrl( GetRedirectUri(), GetRedirectUrlAfterLogin() );
// Use the route passed from the client to build the redirect URI.
// The page route is not currently available within a block action.
var loginUrl = externalRedirectAuthentication.GenerateExternalLoginUrl( GetRedirectUri( bag.Route ), GetRedirectUrlAfterLogin() );

if ( loginUrl == null )
{
Expand Down Expand Up @@ -735,10 +737,28 @@ private IEnumerable<NamedComponent<AuthenticationComponent>> GetAuthenticationCo
/// <summary>
/// Gets the redirect URI that can be used by external authentication components to complete authentication.
/// </summary>
private string GetRedirectUri()
/// <param name="path">The path to use for the redirect URI.</param>
private string GetRedirectUri( string path )
{
var uri = this.RequestContext.RequestUri;
return uri.Scheme + "://" + uri.GetComponents( UriComponents.HostAndPort, UriFormat.UriEscaped ).EnsureTrailingForwardslash() + $"page/{PageCache.Id}";
// If the path is not valid then default to the current page.
if ( !IsPageRouteValid( path ) )
{
path = this.GetCurrentPageUrl();
}

var uriBuilder = new UriBuilder
{
Scheme = this.RequestContext.RequestUri.Scheme,
Host = this.RequestContext.RequestUri.Host,
Port = this.RequestContext.RequestUri.Port,
Path = path
};

// Build the URI. This will pass a string representation of the URL (including the 443 port) to the Uri constructor.
var uri = uriBuilder.Uri;

// Return the original string that was passed to the Uri constructor (including the 443 port).
return uri.OriginalString;
}

/// <summary>
Expand Down Expand Up @@ -926,6 +946,31 @@ private bool IsExistingUser( UserLogin userLogin )
{
return userLogin?.EntityType != null;
}

/// <summary>
/// Determines whether the specified route is a valid page route.
/// </summary>
/// <param name="route">The route.</param>
/// <returns>
/// <c>true</c> if the specified route is valid page route; otherwise, <c>false</c>.
/// </returns>
private bool IsPageRouteValid( string route )
{
// Ensure the supplied path is a valid page route.
if ( route.IsNullOrWhiteSpace() )
{
return false;
}

var simplifiedRoute = route.ToLower().RemoveLeadingForwardslash().RemoveTrailingForwardslash();

if ( this.PageCache.PageRoutes.Any( r => r.Route?.ToLower().RemoveLeadingForwardslash().RemoveTrailingForwardslash() == simplifiedRoute ) )
{
return true;
}

return simplifiedRoute == $"page/{this.PageCache.Id}";
}

/// <summary>
/// Determines whether the <paramref name="credentialLoginRequestBag"/> is valid.
Expand Down Expand Up @@ -1007,7 +1052,7 @@ private bool IsUserLockedOut( UserLogin userLogin, out string lockedOutMessage )
/// <param name="externalAuthProviders">The external authentication providers.</param>
private void LogInWithExternalAuthProviderIfNeeded( LoginInitializationBox box, List<NamedComponent<AuthenticationComponent>> externalAuthProviders )
{
var redirectUrl = GetRedirectUri();
var redirectUrl = GetRedirectUri( this.RequestContext.RequestUri.AbsolutePath );

foreach ( var authProvider in externalAuthProviders.Select( c => c.Component ) )
{
Expand Down Expand Up @@ -1091,7 +1136,7 @@ private void RedirectToSingleExternalAuthProviderIfNeeded( LoginInitializationBo
return;
}

var authLoginUri = externalRedirectAuthentication.GenerateExternalLoginUrl( GetRedirectUri(), GetRedirectUrlAfterLogin() ).AbsoluteUri;
var authLoginUri = externalRedirectAuthentication.GenerateExternalLoginUrl( GetRedirectUri( this.RequestContext.RequestUri.AbsolutePath ), GetRedirectUrlAfterLogin() ).AbsoluteUri;

if ( authLoginUri.IsNotNullOrWhiteSpace() )
{
Expand Down
3 changes: 2 additions & 1 deletion Rock.JavaScript.Obsidian.Blocks/src/Security/login.obs
Expand Up @@ -190,7 +190,8 @@
async function onExternalLogin(externalLogin: ExternalAuthenticationButtonBag): Promise<void> {
isAuthenticating.value = true;
const bag: RemoteLoginStartRequestBag = {
authenticationType: externalLogin.authenticationType
authenticationType: externalLogin.authenticationType,
route: location.pathname
};

try {
Expand Down
Expand Up @@ -25,4 +25,7 @@
export type RemoteLoginStartRequestBag = {
/** Gets or sets the authentication entity type guid. */
authenticationType?: string | null;

/** Gets or sets the current URL path. */
route?: string | null;
};
Expand Up @@ -25,5 +25,13 @@ public class RemoteLoginStartRequestBag
/// Gets or sets the authentication entity type guid.
/// </summary>
public string AuthenticationType { get; set; }

/// <summary>
/// Gets or sets the current URL path.
/// </summary>
/// <value>
/// The current URL path.
/// </value>
public string Route { get; set; }
}
}

0 comments on commit 3340780

Please sign in to comment.