I'm currently working on the same type of project. This is what I have found out so far.
There is 4 Separate Concerns.
- Identity Server - Maintains Authenticating Users / Clients / Scope
- WebApi - Consumes Token generated by Identity Server for Authorization & Identity Information of User.
- WebForms / JQuery - For my project currently handles authentication for existing functionality redirects to the new WebApi.
- HTML using Javascript - Strictly uses WebApi for Information.
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