Browse Source

Update OpenIddictApplication.PostLogoutRedirectUris/RedirectUris and OpenIddictAuthorization.Scopes to be stored as JSON arrays

pull/545/head
Kévin Chalet 8 years ago
parent
commit
98651b9e34
  1. 98
      src/OpenIddict.Core/Stores/OpenIddictApplicationStore.cs
  2. 18
      src/OpenIddict.Core/Stores/OpenIddictAuthorizationStore.cs
  3. 10
      src/OpenIddict.Models/OpenIddictApplication.cs
  4. 4
      src/OpenIddict.Models/OpenIddictAuthorization.cs

98
src/OpenIddict.Core/Stores/OpenIddictApplicationStore.cs

@ -140,40 +140,27 @@ namespace OpenIddict.Core
throw new ArgumentException("The address cannot be null or empty.", nameof(address)); throw new ArgumentException("The address cannot be null or empty.", nameof(address));
} }
// To optimize the efficiency of the query, only applications whose stringified // To optimize the efficiency of the query a bit, only applications whose stringified
// LogoutRedirectUris property contains the specified address are returned. Once the // PostLogoutRedirectUris contains the specified URL are returned. Once the applications
// applications are retrieved, the LogoutRedirectUri property is manually split. // are retrieved, a second pass is made to ensure only valid elements are returned.
// Implementers that use this method in a hot path may want to override this method
// to use SQL Server 2016 functions like JSON_VALUE to make the query more efficient.
IQueryable<TApplication> Query(IQueryable<TApplication> applications, string uri) IQueryable<TApplication> Query(IQueryable<TApplication> applications, string uri)
=> from application in applications => from application in applications
where application.PostLogoutRedirectUris.Contains(uri) where application.PostLogoutRedirectUris.Contains(uri)
select application; select application;
var candidates = await ListAsync((applications, uri) => Query(applications, uri), address, cancellationToken); var builder = ImmutableArray.CreateBuilder<TApplication>();
if (candidates.IsDefaultOrEmpty)
{
return ImmutableArray.Create<TApplication>();
}
var builder = ImmutableArray.CreateBuilder<TApplication>(0); foreach (var application in await ListAsync((applications, uri) => Query(applications, uri), address, cancellationToken))
foreach (var candidate in candidates)
{ {
var uris = candidate.PostLogoutRedirectUris?.Split( foreach (var uri in await GetPostLogoutRedirectUrisAsync(application, cancellationToken))
new[] { OpenIddictConstants.Separators.Space },
StringSplitOptions.RemoveEmptyEntries);
if (uris == null)
{
continue;
}
foreach (var uri in uris)
{ {
// Note: the post_logout_redirect_uri must be compared // Note: the post_logout_redirect_uri must be compared
// using case-sensitive "Simple String Comparison". // using case-sensitive "Simple String Comparison".
if (string.Equals(uri, address, StringComparison.Ordinal)) if (string.Equals(uri, address, StringComparison.Ordinal))
{ {
builder.Add(candidate); builder.Add(application);
break; break;
} }
@ -199,40 +186,27 @@ namespace OpenIddict.Core
throw new ArgumentException("The address cannot be null or empty.", nameof(address)); throw new ArgumentException("The address cannot be null or empty.", nameof(address));
} }
// To optimize the efficiency of the query, only applications whose stringified // To optimize the efficiency of the query a bit, only applications whose stringified
// RedirectUris property contains the specified address are returned. Once the // RedirectUris property contains the specified URL are returned. Once the applications
// applications are retrieved, the RedirectUri property is manually split. // are retrieved, a second pass is made to ensure only valid elements are returned.
// Implementers that use this method in a hot path may want to override this method
// to use SQL Server 2016 functions like JSON_VALUE to make the query more efficient.
IQueryable<TApplication> Query(IQueryable<TApplication> applications, string uri) IQueryable<TApplication> Query(IQueryable<TApplication> applications, string uri)
=> from application in applications => from application in applications
where application.RedirectUris.Contains(uri) where application.RedirectUris.Contains(uri)
select application; select application;
var candidates = await ListAsync((applications, uri) => Query(applications, uri), address, cancellationToken); var builder = ImmutableArray.CreateBuilder<TApplication>();
if (candidates.IsDefaultOrEmpty)
{
return ImmutableArray.Create<TApplication>();
}
var builder = ImmutableArray.CreateBuilder<TApplication>(0); foreach (var application in await ListAsync((applications, uri) => Query(applications, uri), address, cancellationToken))
foreach (var candidate in candidates)
{ {
var uris = candidate.RedirectUris?.Split( foreach (var uri in await GetRedirectUrisAsync(application, cancellationToken))
new[] { OpenIddictConstants.Separators.Space },
StringSplitOptions.RemoveEmptyEntries);
if (uris == null)
{
continue;
}
foreach (var uri in uris)
{ {
// Note: the redirect_uri must be compared using case-sensitive "Simple String Comparison". // Note: the redirect_uri must be compared using case-sensitive "Simple String Comparison".
// See http://openid.net/specs/openid-connect-core-1_0.html#AuthRequest for more information. // See http://openid.net/specs/openid-connect-core-1_0.html#AuthRequest for more information.
if (string.Equals(uri, address, StringComparison.Ordinal)) if (string.Equals(uri, address, StringComparison.Ordinal))
{ {
builder.Add(candidate); builder.Add(application);
break; break;
} }
@ -400,11 +374,7 @@ namespace OpenIddict.Core
return Task.FromResult(ImmutableArray.Create<string>()); return Task.FromResult(ImmutableArray.Create<string>());
} }
var uris = application.PostLogoutRedirectUris.Split( return Task.FromResult(JArray.Parse(application.PostLogoutRedirectUris).Select(element => (string) element).ToImmutableArray());
new[] { OpenIddictConstants.Separators.Space },
StringSplitOptions.RemoveEmptyEntries);
return Task.FromResult(ImmutableArray.Create(uris));
} }
/// <summary> /// <summary>
@ -452,11 +422,7 @@ namespace OpenIddict.Core
return Task.FromResult(ImmutableArray.Create<string>()); return Task.FromResult(ImmutableArray.Create<string>());
} }
var uris = application.RedirectUris.Split( return Task.FromResult(JArray.Parse(application.RedirectUris).Select(element => (string) element).ToImmutableArray());
new[] { OpenIddictConstants.Separators.Space },
StringSplitOptions.RemoveEmptyEntries);
return Task.FromResult(ImmutableArray.Create(uris));
} }
/// <summary> /// <summary>
@ -659,17 +625,7 @@ namespace OpenIddict.Core
return Task.CompletedTask; return Task.CompletedTask;
} }
if (addresses.Any(address => string.IsNullOrEmpty(address))) application.PostLogoutRedirectUris = new JArray(addresses.ToArray()).ToString(Formatting.None);
{
throw new ArgumentException("Callback addresses cannot be null or empty.", nameof(addresses));
}
if (addresses.Any(address => address.Contains(OpenIddictConstants.Separators.Space)))
{
throw new ArgumentException("Callback addresses cannot contain spaces.", nameof(addresses));
}
application.PostLogoutRedirectUris = string.Join(OpenIddictConstants.Separators.Space, addresses);
return Task.CompletedTask; return Task.CompletedTask;
} }
@ -726,17 +682,7 @@ namespace OpenIddict.Core
return Task.CompletedTask; return Task.CompletedTask;
} }
if (addresses.Any(address => string.IsNullOrEmpty(address))) application.RedirectUris = new JArray(addresses.ToArray()).ToString(Formatting.None);
{
throw new ArgumentException("Callback addresses cannot be null or empty.", nameof(addresses));
}
if (addresses.Any(address => address.Contains(OpenIddictConstants.Separators.Space)))
{
throw new ArgumentException("Callback addresses cannot contain spaces.", nameof(addresses));
}
application.RedirectUris = string.Join(OpenIddictConstants.Separators.Space, addresses);
return Task.CompletedTask; return Task.CompletedTask;
} }

18
src/OpenIddict.Core/Stores/OpenIddictAuthorizationStore.cs

@ -246,11 +246,7 @@ namespace OpenIddict.Core
return Task.FromResult(ImmutableArray.Create<string>()); return Task.FromResult(ImmutableArray.Create<string>());
} }
var scopes = authorization.Scopes.Split( return Task.FromResult(JArray.Parse(authorization.Scopes).Select(element => (string) element).ToImmutableArray());
new[] { OpenIddictConstants.Separators.Space },
StringSplitOptions.RemoveEmptyEntries);
return Task.FromResult(ImmutableArray.Create(scopes));
} }
/// <summary> /// <summary>
@ -465,17 +461,7 @@ namespace OpenIddict.Core
return Task.CompletedTask; return Task.CompletedTask;
} }
if (scopes.Any(scope => string.IsNullOrEmpty(scope))) authorization.Scopes = new JArray(scopes.ToArray()).ToString(Formatting.None);
{
throw new ArgumentException("Scopes cannot be null or empty.", nameof(authorization));
}
if (scopes.Any(scope => scope.Contains(OpenIddictConstants.Separators.Space)))
{
throw new ArgumentException("Scopes cannot contain spaces.", nameof(authorization));
}
authorization.Scopes = string.Join(OpenIddictConstants.Separators.Space, scopes);
return Task.CompletedTask; return Task.CompletedTask;
} }

10
src/OpenIddict.Models/OpenIddictApplication.cs

@ -75,9 +75,8 @@ namespace OpenIddict.Models
public virtual string Permissions { get; set; } public virtual string Permissions { get; set; }
/// <summary> /// <summary>
/// Gets or sets the logout callback URLs /// Gets or sets the logout callback URLs associated with
/// associated with the current application, /// the current application, serialized as a JSON array.
/// stored as a unique space-separated string.
/// </summary> /// </summary>
public virtual string PostLogoutRedirectUris { get; set; } public virtual string PostLogoutRedirectUris { get; set; }
@ -88,9 +87,8 @@ namespace OpenIddict.Models
public virtual string Properties { get; set; } public virtual string Properties { get; set; }
/// <summary> /// <summary>
/// Gets or sets the callback URLs /// Gets or sets the callback URLs associated with the
/// associated with the current application, /// current application, serialized as a JSON array.
/// stored as a unique space-separated string.
/// </summary> /// </summary>
public virtual string RedirectUris { get; set; } public virtual string RedirectUris { get; set; }

4
src/OpenIddict.Models/OpenIddictAuthorization.cs

@ -56,8 +56,8 @@ namespace OpenIddict.Models
public virtual string Properties { get; set; } public virtual string Properties { get; set; }
/// <summary> /// <summary>
/// Gets or sets the space-delimited scopes /// Gets or sets the scopes associated with the current
/// associated with the current authorization. /// authorization, serialized as a JSON array.
/// </summary> /// </summary>
public virtual string Scopes { get; set; } public virtual string Scopes { get; set; }

Loading…
Cancel
Save