I am trying for a while to figure out how to solve SSO (Single Sign On) with Thinktecture IdentityServer v3 for a legacy webforms application. Unfortunately I am stacked.
The infrastructure is like this:
I am having the following questions which hopefully will help me to bring things up:
Any help will be much appreciated.
Thanks!
I'm currently working on the same type of project. This is what I have found out so far.
There is 4 Separate Concerns.
The custom grant below is for a user currently logged in through the WebForm as a membership object & I do not want to ask the user again to relogin via Identity Server.
For direct oAuth Authentication check out the sample here..
Sample Javascript Client
Configuring the Javascript an Implicit Flow would work just fine. Save the token connect with the api.
Identity Server v3
I had to configured using
Custom Grant w IUserService
Custom Grants
These will show how to configure a custom grant validation. With the user service you can have the Identity Service query existing users & customize claims.
There is alot of configuration to the Identity Server to make it your own. this is al very well documented on the IdentityServer website I wont go in how to set the basics up.
Ex: Client Configuration
return new List<Client>
{
new Client
{
ClientName = "Custom Grant Client",
Enabled = true,
ClientId = "client",
ClientSecrets = new List<ClientSecret>
{
new ClientSecret("secret".Sha256()),
},
Flow = Flows.Custom,
CustomGrantTypeRestrictions = new List<string>
{
"custom"
}
}
};
WebApi - Resource
Example WebApi Client Sample
Need to have the Nuget package
Thinktecture.IdentityServer.AccessTokenValidation
Startup.cs
app.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions
{
//Location of your identity server
Authority = "https://localhost:44333/core"
});
WebForms BackEnd WebForms Call
Need Nuget Package
Thinktecture.IdentityModel.Client
[WebMethod]
[ScriptMethod(ResponseFormat.Json)]
public static string AuthorizeClient()
{
var client = new OAuth2Client(
//location of identity server, ClientId, ClientSecret
new Uri("http://localhost:44333/core/connect/token"),
"client",
"secret");
//ClientGrantRestriction, Scope (I have a Client Scope of read), Listing of claims
var result = client.RequestCustomGrantAsync("custom", "read", new Dictionary<string, string>
{
{ "account_store", "foo" },
{ "legacy_id", "bob" },
{ "legacy_secret", "bob" }
}).Result;
return result.AccessToken;
}
These are generic claim for this example however I can generate my own claim objects relating to the user to send to the Identity Server & regenerate an Identity for the WebApi to consume.
WebForms / JQuery using
JQuery.cookie
$('#btnTokenCreate').click(function (e) {
//Create Token from User Information
Ajax({
url: "Default.aspx/AuthorizeClient",
type: "POST"
},
null,
function (data) {
sendToken = data.d;
//Clear Cookie
$.removeCookie('UserAccessToken', { path: '/' });
//Make API Wrap Info in Stringify
$.cookie.json = true;
//Save Token as Cookie
$.cookie('UserAccessToken', sendToken, { expires: 7, path: '/' });
});
JQuery WebAPI Ajax Sample Ajax Method - Note the beforeSend.
function Ajax(options, apiToken, successCallback) {
//Perform Ajax Call
$.ajax({
url: options.url,
data: options.params,
dataType: "json",
type: options.type,
async: false,
contentType: "application/json; charset=utf-8",
dataFilter: function (data) { return data; },
//Before Sending Ajax Perform Cursor Switch
beforeSend: function (xhr) {
//Adds ApiToken to Ajax Header
if (apiToken) {
xhr.withCredentials = true;
xhr.setRequestHeader("Authorization", " Bearer " + apiToken);
}
},
// Sync Results
success: function (data, textStatus, jqXHR) {
successCallback(data, textStatus, jqXHR);
},
//Sync Fail Call back
error: function (jqXHR, textStatus, errorThrown) {
console.log(errorThrown);
}
});
}
AngularJS
This has same idea as the JQuery using the
module.run(function($http) {
//Make API Wrap Info in Stringify
$.cookie.json = true;
//Save Token as Cookie
var token = $.cookie('UserAccessToken');
$http.defaults.headers.common.Authorization = 'Bearer ' + token });
This makes the assumption your using the same domain as the WebForm. Otherwise I would use a Query string for a redirect to the Angular page with the token.
For CORS support need to make sure the WebApi has Cors configured for proper functionality. using the
Microsoft.AspNet.WebApi.Cors
Hope this sheds some light on the subject of how to approach this
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With