I am trying to create a demo project which uses .Net ASP.Net WebAPI and KnockoutJs as the front end. I have created the controller methods that listen for the /token post, and validates a user, and returns a token. This is done from an Ajax Post from the Knockout View Model.
This code works. However, when I get 200 back (Success) from the webApi, I then redirect to a controller method, decorated with a [Authorize]. And that's where I hit a 401 - not authorised.
Login()
{
var data = {
username : this.login.emailAddress(),
password : this.login.password(),
RememberMe: this.login.rememberMe(),
grant_type: "password"
}
return $.ajax({
type: "POST",
data: data,
dataType: "json",
url: "/token",
contentType: "application/json"
}).done((reply) => {
window.location.href = "/Home/AnotherThing";
});
}
I think the issue is - I get a response back from my /token (login) call, but do nothing with it. I'm not sure what to do with the token. I stupidly thought that OAuth would somehow put the token into my headers, and they would be there magically. I was wrong.
So, I've been looking for an example, and then best I can find is Here
But this means I am going to have a LOT of repeated code, on each view model
Extract:
function ViewModel() {
var self = this;
var tokenKey = 'accessToken';
var RefTokenKey = 'refreshToken';
self.result = ko.observable();
self.user = ko.observable();
self.token = ko.observable();
self.refreshToken = ko.observable();
function showError(jqXHR) {
self.result(jqXHR.status + ': ' + jqXHR.statusText);
}
self.callApi = function () {
self.result('');
var token = sessionStorage.getItem(tokenKey);
var headers = {};
if (token) {
headers.Authorization = 'Bearer ' + token;
}
$.ajax({
type: 'GET',
url: '/api/values',
headers: headers
}).done(function (data) {
self.result(data);
}).fail(showError);
}
self.callToken = function () {
self.result('');
var loginData = {
grant_type: 'password',
username: self.loginEmail(),
password: self.loginPassword()
};
$.ajax({
type: 'POST',
url: '/Token',
data: loginData
}).done(function (data) {
self.user(data.userName);
// Cache the access token in session storage.
sessionStorage.setItem(tokenKey, data.access_token);
var tkn = sessionStorage.getItem(tokenKey);
$("#tknKey").val(tkn);
}).fail(showError);
}
}
var app = new ViewModel();
ko.applyBindings(app);
This seems to be part of what I am missing:
sessionStorage.setItem(tokenKey, data.access_token);
var tkn = sessionStorage.getItem(tokenKey);
$("#tknKey").val(tkn);
Would I need every view model to have the code that then goes to the sessionStorage, and get the token?
So, this:
var token = sessionStorage.getItem(tokenKey);
var headers = {};
if (token) {
headers.Authorization = 'Bearer ' + token;
}
$.ajax({
type: 'GET',
url: '/api/values',
headers: headers
}).done(function (data) {
self.result(data);
}).fail(showError);
}
It seems like a lot of code.. Is this the right way to go?