I have an IdentityServer3 working with Windows Authentication Service. Now I want to handle the SAML2 protocol on my IdentityServer3 and I saw Kentor could do it for me.
The problem is that Kentor is using OpenID Connect in all samples, I searched a while but i couldn't find any documentation on how to combine Kentor with WindowsAuth. After many tries without success, I come here to ask if it is realy possible and how ?
Here is my (non-working) configuration in Startup.cs :
public void Configuration(IAppBuilder appBuilder)
{
appBuilder.Map("/windows", ConfigureWindowsTokenProvider);
appBuilder.UseIdentityServer(GetIdentityServerOptions());
}
private void ConfigureWsFederation(IAppBuilder pluginApp, IdentityServerOptions options)
{
var factory = new WsFederationServiceFactory(options.Factory);
factory.Register(new Registration<IEnumerable<RelyingParty>>(RelyingParties.Get()));
factory.RelyingPartyService = new Registration<IRelyingPartyService>(typeof(InMemoryRelyingPartyService));
factory.CustomClaimsService = new Registration<ICustomWsFederationClaimsService>(typeof(ClaimsService));
factory.CustomRequestValidator = new Registration<ICustomWsFederationRequestValidator>(typeof(RequestValidator));
var wsFedOptions = new WsFederationPluginOptions
{
IdentityServerOptions = options,
Factory = factory,
};
pluginApp.UseWsFederationPlugin(wsFedOptions);
}
private IdentityServerOptions GetIdentityServerOptions()
{
DefaultViewServiceOptions viewServiceOptions = new DefaultViewServiceOptions();
viewServiceOptions.CustomViewDirectory = HttpContext.Current.Server.MapPath("~/Templates");
viewServiceOptions.Stylesheets.Add("/Content/Custom.css");
IdentityServerServiceFactory factory = new IdentityServerServiceFactory()
.UseInMemoryClients(new List<Client>())
.UseInMemoryScopes(new List<Scope>());
factory.ConfigureDefaultViewService(viewServiceOptions);
factory.UserService = new Registration<IUserService>(resolver => new UserService());
return new IdentityServerOptions
{
SigningCertificate = Certificate.Load(),
Factory = factory,
PluginConfiguration = ConfigureWsFederation,
EventsOptions = new EventsOptions
{
RaiseSuccessEvents = true,
RaiseFailureEvents = true,
},
AuthenticationOptions = new IdentityServer3.Core.Configuration.AuthenticationOptions
{
IdentityProviders = ConfigureIdentityProviders,
EnableLocalLogin = false,
},
RequireSsl = true,
};
}
private void ConfigureIdentityProviders(IAppBuilder app, string signInAsType)
{
ConfigureWSFederationProvider(app, signInAsType);
ConfigureKentorProvider(app, signInAsType);
}
private void ConfigureKentorProvider(IAppBuilder app, string signInAsType)
{
SPOptions spOptions = new SPOptions
{
EntityId = new EntityId("Dropbox"),
};
KentorAuthServicesAuthenticationOptions kentorOptions = new KentorAuthServicesAuthenticationOptions(false)
{
Caption = "Windows",
SignInAsAuthenticationType = signInAsType,
SPOptions = spOptions,
};
IdentityProvider idp = new IdentityProvider(new EntityId("http://stubidp.kentor.se/Metadata"), spOptions)
{
Binding = Saml2BindingType.HttpRedirect,
AllowUnsolicitedAuthnResponse = true,
LoadMetadata = true,
};
kentorOptions.IdentityProviders.Add(idp);
app.UseKentorAuthServicesAuthentication(kentorOptions);
}
private void ConfigureWSFederationProvider(IAppBuilder app, string signInAsType)
{
app.UseWsFederationAuthentication(new WsFederationAuthenticationOptions()
{
AuthenticationType = "windows",
Caption = "Windows",
SignInAsAuthenticationType = signInAsType,
MetadataAddress = serverHost + "windows",
Wtrealm = "urn:idsrv3",
});
}
private void ConfigureWindowsTokenProvider(IAppBuilder app)
{
app.UseWindowsAuthenticationService(new WindowsAuthenticationOptions
{
IdpReplyUrl = serverHost,
SigningCertificate = Certificate.Load(),
EnableOAuth2Endpoint = false,
});
}
This configuration builds, but when I use the Dropbox SSO (using SAML2) I get the exception No Idp with entity id "Dropbox" found.
You've configured "Dropbox" as the identity (EntityId in SAML2 terms) of your application (the one in SpOptions). That should be a URI that identifies your application. The convention is to use the URL to the metadata (~/AuthServices).
You need to add an IdentityProvider with the settings of the dropbox idp. Please also note that an EntityId of "Dropbox" won't work as the SAML2 standard requires an Entity ID to be an absolute URI.
Related
I'm using OWIN 4.2 with .NET Framework 4.7.2 for my ASP.NET MVC client app.
Login works completely fine but logout will fail.
On my client's startup.cs
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions
{
ClientId = "MVC",
ClientSecret = "MVC-Secret",
Authority = "https://localhost:44305/",
RedirectUri = "https://localhost:44347/",
CallbackPath = new PathString("/"),
Scope = "openid api",
SignInAsAuthenticationType = "cookie",
RequireHttpsMetadata = false,
UseTokenLifetime = false,
RedeemCode = true,
SaveTokens = true,
ResponseType = OpenIdConnectResponseType.Code,
ResponseMode = OpenIdConnectResponseMode.Query,
// OpenIdConnectAuthenticationNotifications configures OWIN to send notification of failed authentications to the OnAuthenticationFailed method
Notifications = new OpenIdConnectAuthenticationNotifications
{
AuthenticationFailed = OnAuthenticationFailed,
RedirectToIdentityProvider = n =>
{
if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.Authentication)
{
// generate code verifier and code challenge
var codeVerifier = CryptoRandom.CreateUniqueId(32);
string codeChallenge;
using (var sha256 = SHA256.Create())
{
var challengeBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(codeVerifier));
codeChallenge = Base64Url.Encode(challengeBytes);
}
// set code_challenge parameter on authorization request
n.ProtocolMessage.SetParameter("code_challenge", codeChallenge);
n.ProtocolMessage.SetParameter("code_challenge_method", "S256");
// remember code verifier in cookie (adapted from OWIN nonce cookie)
// see: https://github.com/scottbrady91/Blog-Example-Classes/blob/master/AspNetFrameworkPkce/ScottBrady91.BlogExampleCode.AspNetPkce/Startup.cs#L85
RememberCodeVerifier(n, codeVerifier);
}
if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.Logout)
{
var idTokenHint = n.OwinContext.Authentication.User.FindFirst("id_token").Value;
if (idTokenHint != null)
{
n.ProtocolMessage.IdTokenHint = idTokenHint;
}
}
return Task.CompletedTask;
},
AuthorizationCodeReceived = n =>
{
// get code verifier from cookie
// see: https://github.com/scottbrady91/Blog-Example-Classes/blob/master/AspNetFrameworkPkce/ScottBrady91.BlogExampleCode.AspNetPkce/Startup.cs#L102
var codeVerifier = RetrieveCodeVerifier(n);
// attach code_verifier on token request
n.TokenEndpointRequest.SetParameter("code_verifier", codeVerifier);
return Task.CompletedTask;
},
SecurityTokenValidated = n =>
{
var id = n.AuthenticationTicket.Identity;
id.AddClaim(new Claim("id_token", n.ProtocolMessage.IdToken));
n.AuthenticationTicket = new AuthenticationTicket(
id,
n.AuthenticationTicket.Properties);
return Task.FromResult(0);
},
}
}
);
I also tried
...
Authority = "https://localhost:44305/",
RedirectUri = "https://localhost:44347/",
PostLogoutRedirectUri = "https://localhost:44347/signout-callback-oidc",
...
And also
...
Authority = "https://localhost:44305/",
RedirectUri = "https://localhost:44347/",
PostLogoutRedirectUri = "https://localhost:44347/",
...
However, all these results in the response
error:invalid_request
error_description:The specified 'post_logout_redirect_uri' is invalid.
error_uri:https://documentation.openiddict.com/errors/ID2052
On my server, the configuration is as follows
await manager.CreateAsync(new OpenIddictApplicationDescriptor
{
ClientId = clientId,
ClientSecret = clientSecret,
DisplayName = displayName,
RedirectUris =
{
new Uri("https://localhost:44347/")
},
Permissions =
{
...
},
PostLogoutRedirectUris =
{
new Uri("https://localhost:44347/")
}
}, cancellationToken);
}
I have also tried changing Server config to
PostLogoutRedirectUris =
{
new Uri("https://localhost:44347/signout-callback-oidc")
}
I encountered the same issue, what solved it for me was to add the logout permission in the application - OpenIddictConstants.Permissions.Endpoints.Logout
await _applicationManager.CreateAsync(new OpenIddictApplicationDescriptor
{
ClientId = "mvc",
ClientSecret = "901564A5-E7FE-42CB-B10D-61EF6A8F3654",
DisplayName = "MVC client application",
PostLogoutRedirectUris = { new Uri("http://localhost:53507/signout-callback-oidc") },
RedirectUris = { new Uri("http://localhost:53507/signin-oidc") },
Permissions =
{
OpenIddictConstants.Permissions.Endpoints.Authorization,
OpenIddictConstants.Permissions.Endpoints.Logout,
OpenIddictConstants.Permissions.Endpoints.Token,
OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode
}
});
As answered by Apps in here https://stackoverflow.com/a/69671657/6477254, I can confirm that you must allow permission for the logout endpoint, using the constant value of OpenIddictConstants.Permissions.Endpoints.Logout, which hold "ept:logout" string value when creating the OpenIddict data.
I am trying to implement PersistedGrantStore on mongodb. I have seen similar questions and answers but no luck so far (How can I implement PersistedGrantStore on my mongodb database).
I have created a class inhertied from IPersistedGrantStore I have inject it in DI using AddTransient, but still no call is made within my class. Here is a section of my code within ConfigureServices(IServiceCollection services) function of startup.cs
services.AddAuthentication(o =>
{
o.DefaultScheme = IdentityServerAuthenticationDefaults.AuthenticationScheme;
o.DefaultAuthenticateScheme = IdentityServerAuthenticationDefaults.AuthenticationScheme;
}).AddIdentityServerAuthentication(options =>
{
options.SaveToken = true;
options.Authority = authorityServerURL;// "https://demo.identityserver.io";
//options.ApiName = "BWalle_API";
//options.ApiSecret = "Odsdffegfgdfgdfglq_";
options.RequireHttpsMetadata = false;
options.EnableCaching = false;
options.SupportedTokens = SupportedTokens.Jwt;
});
var builder = services.AddIdentityServer(options =>
{
options.Endpoints.EnableUserInfoEndpoint = true;
options.Events = new EventsOptions()
{
RaiseErrorEvents = true,
RaiseFailureEvents = true,
RaiseInformationEvents = true,
RaiseSuccessEvents = true
};
})
.AddTestUsers(Config.GetUsers())
.AddSigningCredential(new Microsoft.IdentityModel.Tokens.SigningCredentials(GetSecurityKey(), SecurityAlgorithms.RsaSha512Signature))
.AddResourceStore<ResourceStore>()
.AddClientStore<ClientStore>()
.AddProfileService<MongoDbProfileService>()
.AddResourceOwnerValidator<MongoDbResourceOwnerPasswordValidator>()
.AddJwtBearerClientAuthentication();
builder.Services.AddTransient<IPersistedGrantStore, PersistedGrantStore>();
And this is the ClientStore Class:
public class ClientStore : IClientStore
{
Task<Client> IClientStore.FindClientByIdAsync(string clientId)
{
Client client = new Client
{
ClientId = "BWalle_API",
ClientName = "BWalle API Client",
//AllowAccessTokensViaBrowser = true,
//AlwaysSendClientClaims = true,
AllowedGrantTypes = new List<string>() {
GrantType.ResourceOwnerPassword,
GrantType.Hybrid,
GrantType.ClientCredentials
},
ClientSecrets = new List<Secret>
{
new Secret("Odsdffegfgdfgdfglq_".Sha512())
},
AllowedScopes = new List<string>
{
IdentityServer4.IdentityServerConstants.StandardScopes.OpenId,
IdentityServer4.IdentityServerConstants.StandardScopes.Profile,
IdentityServer4.IdentityServerConstants.StandardScopes.Email,
IdentityServer4.IdentityServerConstants.StandardScopes.OfflineAccess,
IdentityServer4.IdentityServerConstants.StandardScopes.Phone,
"BWalle_API"
},
Enabled = true,
//AllowedCorsOrigins = new List<string>
//{
// "http://localhost:4200"
//},
AllowOfflineAccess = true,
AllowRememberConsent = false,
AccessTokenType = AccessTokenType.Jwt,
IdentityTokenLifetime = 3600 * 24, // Lifetime to identity token in seconds (defaults to 300 seconds / 5 minutes)
AccessTokenLifetime = 3600 * 24, //3600, // Lifetime of access token in seconds (defaults to 3600 seconds / 1 hour)
AuthorizationCodeLifetime = 3600 * 24, // Lifetime of authorization code in seconds (defaults to 300 seconds / 5 minutes)
RefreshTokenUsage = TokenUsage.ReUse,
RefreshTokenExpiration = TokenExpiration.Sliding,
UpdateAccessTokenClaimsOnRefresh = true,
IncludeJwtId = true
};
return Task.FromResult<Client>(client);
}
}
And this is the PersistedGrantStore Class:
public class PersistedGrantStore : IPersistedGrantStore
{
private readonly IAppRepository appRepository;
public PersistedGrantStore(IAppRepository DBAppRepository)
{
this.appRepository = DBAppRepository;
}
public Task<IEnumerable<PersistedGrant>> GetAllAsync(string subjectId)
{
throw new NotImplementedException();
}
public Task<PersistedGrant> GetAsync(string key)
{
throw new NotImplementedException();
}
public Task RemoveAllAsync(string subjectId, string clientId)
{
throw new NotImplementedException();
}
public Task RemoveAllAsync(string subjectId, string clientId, string type)
{
throw new NotImplementedException();
}
public Task RemoveAsync(string key)
{
throw new NotImplementedException();
}
public Task StoreAsync(PersistedGrant grant)
{
throw new NotImplementedException();
}
}
I am using those nuget packages:
Identityserver4\2.1.3,
Identityserver4.AccessTokenValidation\2.5.0
Contrib.Microsoft.aspnetcore.identity.mongodb\2.0.5
I have managed successfully to use mongodb to store users and client and now I am trying to store grants instead of using in memory grant stores but no call is made whith in PersistedGrantStore class.
I am using ResourceOwner as GrantType (JWT - Bearer Model).
I can not see what I am missing, any help would be realy helpfull!!!
Solved!!!! What was missing was adding to the scope the 'offline_access' when sending from client to the server the connection request to the endpoint '/connect/token'.
Example of post '/connect/token' with data in body :
client_id=BWalle_API&client_secret=mysecretAPlq_&grant_type=password&scope=BWalle_API offline_access&username=undefined&password=undefined&rememberme=&VerCode=1820-0327-2104-0012
I am having some issues getting swagger to work with oauth2.
I have created a client in my database like this:
private static void CreateSwaggerClient(DatabaseContext context)
{
var client = new Client
{
ClientId = "swaggerui",
ClientName = "Swagger UI client",
Flow = Flows.Implicit,
Enabled = true,
EnableLocalLogin = true,
AccessTokenType = AccessTokenType.Reference,
AllowAccessTokensViaBrowser = true,
IdentityTokenLifetime = 300,
AccessTokenLifetime = 3600,
AuthorizationCodeLifetime = 300,
AbsoluteRefreshTokenLifetime = 2592000,
SlidingRefreshTokenLifetime = 1296000,
RedirectUris = new List<ClientRedirectUri>
{
new ClientRedirectUri { Uri = "http://localhost:62668/swagger" }
},
AllowedScopes = new List<ClientScope>()
{
new ClientScope
{
Scope = "api"
}
},
ClientSecrets = new List<ClientSecret>()
{
new ClientSecret
{
Value = "secret".Sha256(),
Type = "SharedSecret"
}
}
};
context.Clients.Add(client);
context.SaveChanges();
}
Which has access to my api Scope:
private static void CreateScope(DatabaseContext context)
{
var scope = new Scope
{
Enabled = true,
Name = "api",
DisplayName = "Cormar API",
Description = "Should only be used for trusted internal service side applications",
Required = true,
Emphasize = true,
Type = (int)ScopeType.Resource,
IncludeAllClaimsForUser = false,
ShowInDiscoveryDocument = true,
AllowUnrestrictedIntrospection = true,
ScopeClaims = new List<ScopeClaim>()
{
new ScopeClaim
{
Name = "role",
Description = "Role claim types",
AlwaysIncludeInIdToken = true
},
new ScopeClaim
{
Name = "name",
Description = "The name of the user",
AlwaysIncludeInIdToken = true
},
new ScopeClaim
{
Name ="password",
Description = "Contains the encrypted password for a user",
AlwaysIncludeInIdToken = true
}
},
ScopeSecrets = new List<ScopeSecret>()
{
new ScopeSecret
{
Value = "anothersecret".Sha256(),
Type = "SharedSecret"
}
}
};
context.Scopes.Add(scope);
context.SaveChanges();
}
If I open a browser and navigate to the authorize url like this: https://localhost:44313/identity/connect/authorize?client_id=swaggerui&redirect_uri=http://localhost:62668/swagger&response_type=token&scope=api&state=moo it takes me to a login page, which when I type the username and password brings me to the swagger page with a access_token appended to the URL like this:
#access_token=b49fe5641519c325c17d248d2372d69f&token_type=Bearer&expires_in=3600&scope=api&state=moo
But the issue here is that if I click anything, the access token is removed from the url and if I try any of my endpoints, they all fail with access denied.
I have setup my swagger config like this:
private static void ConfigureSwagger(HttpConfiguration config)
{
config.EnableSwagger(c =>
{
c.SingleApiVersion("v1", "test API");
var baseDirectory = AppDomain.CurrentDomain.BaseDirectory;
var commentsFileName = Assembly.GetExecutingAssembly().GetName().Name + ".XML";
var commentsFile = Path.Combine(baseDirectory, "bin", commentsFileName);
c.IncludeXmlComments(commentsFile);
c.OAuth2("oauth2")
.Description("OAuth2 Implicit Grant")
.Flow("implicit")
.AuthorizationUrl("http://localhost:62668/identity/connect/authorize")
.TokenUrl("http://localhost:62668/identity/connect/token")
.Scopes(scopes =>
{
scopes.Add("api", "api access");
});
c.OperationFilter<AssignOAuth2SecurityRequirements>();
}).EnableSwaggerUi(c =>
{
c.EnableOAuth2Support("swaggerui", "secret", "local", "test");
});
}
Can anyone tell me what I am missing?
I managed to get this working.
First of all, my AssignOAuth2SecurityRequirements was setup incorrectly. I actually found the right code here: http://knowyourtoolset.com/2015/08/secure-web-apis-with-swagger-swashbuckle-and-oauth2-part-2/
public class AssignOAuth2SecurityRequirements: IOperationFilter
{
public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
{
var actFilters = apiDescription.ActionDescriptor.GetFilterPipeline();
var allowsAnonymous = actFilters.Select(f => f.Instance).OfType<OverrideAuthorizationAttribute>().Any();
if (allowsAnonymous)
return; // must be an anonymous method
//var scopes = apiDescription.ActionDescriptor.GetFilterPipeline()
// .Select(filterInfo => filterInfo.Instance)
// .OfType<AllowAnonymousAttribute>()
// .SelectMany(attr => attr.Roles.Split(','))
// .Distinct();
if (operation.security == null)
operation.security = new List<IDictionary<string, IEnumerable<string>>>();
var oAuthRequirements = new Dictionary<string, IEnumerable<string>>
{
{"oauth2", new List<string> {"api"}}
};
operation.security.Add(oAuthRequirements);
}
}
Next, the redirect_uris for my client were incorrect. They all have to be https and they need the full redirect uri. Mine became this:
new ClientRedirectUri { Uri = "https://localhost:44313/swagger/ui/o2c-html" },
Once these were set up, it all started working.
It looks like the Application object in Microsoft.Azure.ActiveDirectory.GraphClient allows a Webapplication to be created. I cannot see how I can use this to create a new Native application.
thanks
Updates:
TaskCompletionSource<string> tcs = new TaskCompletionSource<string>();
tcs.SetResult(accessToken);
var graphClient = new ActiveDirectoryClient(
new Uri($"{GraphApiBaseUrl}{tenantId}"),
async () => { return await tcs.Task; });
var password = Guid.NewGuid().ToString("N");
var cred = new PasswordCredential()
{
StartDate = DateTime.UtcNow,
EndDate = DateTime.UtcNow.AddYears(1),
Value = password
};
var app = await GetApplicationByUrlAsync(accessToken, tenantId, appName, identifierUrl);
if(app == null)
{
app = new Application()
{
DisplayName = appName,
Homepage = homePageUrl,
IdentifierUris = new List<string>() { identifierUrl },
LogoutUrl = logoutUrl,
ReplyUrls = new List<string>() { replyUrl },
PasswordCredentials = new List<PasswordCredential>() { cred },
};
await graphClient.Applications.AddApplicationAsync(app);
}
The fact that an app is a native client application is identified by the PublicClient boolean property on the Application object. (See client types from the OAuth 2.0 spec.)
So, you could register a native client app with the following code:
var app = new Application()
{
DisplayName = "My native client app",
ReplyUrls = new List<string>() { "urn:ietf:wg:oauth:2.0:oob" },
PublicClient = true
};
await graphClient.Applications.AddApplicationAsync(app);
Console.WriteLine("App created. AppId: {0}, ObjectId: {1}", app.AppId, app.ObjectId);
Note that the native client app does not have password credentials or key credentials (or any other secret).
Details about these and other properties of Application objects are available in the API reference documentation: https://msdn.microsoft.com/en-us/library/azure/ad/graph/api/entity-and-complex-type-reference#application-entity
I just set up a SelfHost(InMem with WS-Fed) Thinktecture IdentityServer3 project example and I'm trying to use it to get a JWT, the problem is that I only recieve tokens signed with an asymmetric key using the alg RS256 but I need them to be symmetric using the alg HS256 so I can use the same key on the client.
I have tried to follow some examples by configuring the Relying Party on the server with no success.
For example, I see the following markup:
var relyingParty = new RelyingParty()
{
Enabled = true,
Realm = "urn:carbon",
Name = "Test party",
SymmetricSigningKey =
Convert.FromBase64String("R03W9kJERSSLH11Px+R/O7EYfAadSMQfZD5haQZj6eU="),
TokenLifeTime = 120
};
But when I try it on my code, I have an error on SymmetricSigningKey and it says that:
'Thinktecture.IdentityServer.WsFederation.Models.RelyingParty' does
not contain a definition for 'SymmetricSigningKey'
What am I doing wrong?, thanks in advance!
UPDATE
Markup of the startup file:
public void Configuration(IAppBuilder appBuilder)
{
var factory = InMemoryFactory.Create(
users: Users.Get(),
clients: Clients.Get(),
scopes: Scopes.Get()
);
var options = new IdentityServerOptions
{
IssuerUri = "https://idsrv3.com",
SiteName = "Thinktecture IdentityServer3 - WsFed",
SigningCertificate = Certificate.Get(),
Factory = factory,
PluginConfiguration = ConfigurePlugins,
};
appBuilder.UseIdentityServer(options);
}
private void ConfigurePlugins(IAppBuilder pluginApp, IdentityServerOptions options)
{
var wsFedOptions = new WsFederationPluginOptions(options);
// data sources for in-memory services
wsFedOptions.Factory.Register(new Registration<IEnumerable<RelyingParty>>(RelyingParties.Get()));
wsFedOptions.Factory.RelyingPartyService = new Registration<IRelyingPartyService>(typeof(InMemoryRelyingPartyService));
pluginApp.UseWsFederationPlugin(wsFedOptions);
}
Markup of the scope used:
new Scope
{
Name = "api1"
}
Markup of the client used:
new Client
{
ClientName = "Silicon on behalf of Carbon Client",
ClientId = "carbon",
Enabled = true,
AccessTokenType = AccessTokenType.Jwt,
Flow = Flows.ResourceOwner,
ClientSecrets = new List<ClientSecret>
{
new ClientSecret("21B5F798-BE55-42BC-8AA8-0025B903DC3B".Sha256())
}
}
Markup of the user used:
new InMemoryUser{Subject = "bob", Username = "bob", Password = "bob",
Claims = new Claim[]
{
new Claim(Constants.ClaimTypes.GivenName, "Bob"),
new Claim(Constants.ClaimTypes.FamilyName, "Smith"),
new Claim(Constants.ClaimTypes.Email, "BobSmith#email.com")
}
}
UPDATE
I just check the class model of the relying party of IdentityServer3 and there's no property for the symmetric signing key... I'm lost...
Any ideas?