I am using ASP.NET SPA template, but remaking it to work with AngularJS instead of KnockoutJS. The thing, I have trouble with, is with authorization access token. By default in this template, authorization access token is retrieved, by redirecting user to /Account/Authorize?client_id=web&response_type=token, after that, user is redirected to home with /#access_token=TOKEN_HERE&token_type=bearer&expires_in=1209600 as an arguments. In KO template, there is this common object with function getFragment which reads this url argument, and returns this access token. In template, there is this code, which executes every time page is reloaded
if (!dataModel.getAccessToken()) {
// The following code looks for a fragment in the URL to get the access token which will be
// used to call the protected Web API resource
var fragment = common.getFragment();
if (fragment.access_token) {
// returning with access token, restore old hash, or at least hide token
window.location.hash = fragment.state || '';
dataModel.setAccessToken(fragment.access_token);
} else {
// no token - so bounce to Authorize endpoint in AccountController to sign in or register
window.location = "/Account/Authorize?client_id=web&response_type=token&state=" + encodeURIComponent(window.location.hash);
}
}
dataModel.get/setAccessToken stores token as a variable in LocalStorage.
I was trying to plug this piece of code into AngularJS controller, redirect user, if there is no access token in localstorage. But if I use ngRoute, it messes with response. It changes URL to default route, set in app.Config, and it clears returned token from URL before I can read it.
Can you help me figure out, how and where should I really use this?
This is kind of a generic solution, I'd rip out the ASP.NET SPA stuff. Maybe with Knockout the ASP.NET SPA template provided some value but Angular can do all of what you're trying to do without having to fight your server side template.
Ideally your Angular application is treated like any other client (Android or iOS) to your backend services. Your backend API can expose all the functionality you need, including authentication - there's no reason to pull your user out of your Angular application just to authenticate.
If you would like to bootstrap your application an alternative to ASP.NET SPA would be to use a Yeoman generator. Try out the Angular Fullstack generator, it does a pretty good job of demonstrating how you can authenticate a user within your Angular application.
Related
I have a web app and I am using firebase authentication to login/signup our users.
In the past I have used Passport for login in my app which works but you have to maintain your own database and security blah blah... but I can control when my user can visit a page after logging via Passport using middleware like this -
// isAuthentcated is my middleware on server side.
app.get('/home', isAuthenticated,(req,res)=>{
res.render('home');
});
How can I do the same using firebase because there isn't any mechanism to do that. I have read different answers on stackoverflow and most of the pople are suggesting something like below which obviously isn't secure. Anybody can just type home.html and get to the page.
firebase.auth().onAuthStateChanged(user => {
if(user) {
window.location = 'home.html'; //After successful login, user will be redirected to home.html
}
});
Although, I have thought of using firebase-admin sdk token verification and try to follow the suggestion here but I don't know how it can be useful to do that on server side. Do you guys have any suggestions? How do you redirect user to a new page. An ajax post/get request from a client to a route '/home' with a header containing 'Bearer token' just validate the token but doesn't redirect user because it is a ajax call which is meant for updating a portion of a page.
Now, the question really is, Is it even possible to do that with firebase authentication?
If you host your site on App Engine you can send the ID token of the client with the request for the HTML. This could take the form of a cookie, a parameter, or whatever you choose to securely transfer the token from client to server.
Then the server can use the Firebase Admin SDK to verify the ID token, and use whatever logic you need to determine whether the request is authorized.
I'm working on chrome extension (provides main functionality) and the complementary website (mostly profile and billing related functionality) both backed with firebase backend.
I'm wondering if it's possible to implement the below scenario:
user logs in with the extension using firebase authentication (with firebaseUI lib)
I store a token that I can use to reauthenticate that user (is there such a token?)
when user opens the website, I login that user automatically with the token.
While both the extension and the website has their login/signup forms I'm wondering if it's possible to login user in the extension and to somehow automatically login that same user on the website so they don't have to enter their credentials twice?
So far I was hoping that I could use something like below:
firebase.auth().currentUser.getIdToken(true).then(function(idToken) {
console.log("idToken = ", idToken)
})
And then to use that idToken like this, since if I understand correctly, it's an AWT:
firebase.auth().signInWithCustomToken(idToken).catch(function(error) {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
console.log("signInWithCustomToken: error = ", error)
})
But it gives the following error:
code: "auth/invalid-custom-token"
message: "The custom token format is incorrect. Please check the documentation."
I can parse the token on https://jwt.io/ which shows all the user information but in the end it says "invalid signature"
So I guess this token can be only used to check authentication (like admin.auth().verifyIdToken(idToken)) but not to login user. Am I right?
I know I can create a custom token, but is there any straightforward way to workaround that and to login user from one place only using firebase funstionality? (of course without storing username/password)
You can't sign in with a Firebase ID token. What you can do is the following:
Keep the user session in the chrome extension and run all authenticated requests from there. Use postMessage (with origin verification) to talk with extension from app anytime a request is to be sent. With this you don't have to worry about session synchronization and no Firebase tokens are stored or passed to the web app or every web app that can access the extension.
Add a postMessage API to get an ID token from the extension after verifying the origin of the request. You can then send the request from the web app with the ID token. (less secure than 1 but easier to implement and session is stored in one place).
Create an HTTP endpoint that takes an ID token and returns a custom token. This would verifyIdToken and then create a corresponding custom token for that user using createCustomToken provided by Admin SDK. You then postMessage that from chrome extension to the web page after verifying origin and signInWithCustomToken with that custom token in that web app. This is the least secure as you are providing an endpoint to exchange a short lived ID token with an indefinite session. You will also deal with synchronization issues (user signs out from chrome extension, you have to sign out from websites, etc).
When login with Server-Side flow, or ask authorization for additional scopes, with auth2.grantOfflineAccess, the result access/refresh token is not getting combined with previous authorized scopes, overriding the previous ones.
Even passing the param to js calls, e.g. auth2.grantOfflineAccess({'include_granted_scopes' : 'true', ...}), the param include_granted_scopes=true is NOT added to the generated URL.
When I manually append the param &include_granted_scopes=true to the generated url on popup window, the incremental combined authorization works, as described in the protocol.
Are there any way to make incremental combined authorization with Google SignIn for Server-Side Apps?
Cheers
I am using Visual Studio 2015 Enterprise and ASP.NET vNext Beta8 to issue and consume JWT tokens as described here.
In our implementation we're storing some client details in Redis at token issuing time and we would like the flush this information when the user logs out.
My question is what is the best practices for logging out with OIDC?
While I could roll my own contoller for this purpose I couldn't help but notice Open ID Connect (OIDC) seems somewhat primed to handle this case. For example OIDC has an OnLogoutEndpoint handler and LogoutEndpointPath settings. But when I call the OIDC logout URI that handler appears to accept any random x-www-form-urlencoded form I throw at it and doesn't in any particular way seem to be demanding the presence of a token.
Any advice on proper OIDC logout practices would be very much appreciated.
In AspNet.Security.OpenIdConnect.Server, the logic used for the logout endpoint is left as an exercise.
In this sample, it is implemented using an MVC 6 controller, where you're - of course - free to add custom logic to remove cached details from your Redis server.
[HttpPost("~/connect/logout")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Logout() {
// When invoked, the logout endpoint might receive an unauthenticated request if the server cookie has expired.
// When the client application sends an id_token_hint parameter, the corresponding identity can be retrieved using AuthenticateAsync.
var identity = await HttpContext.Authentication.AuthenticateAsync(OpenIdConnectServerDefaults.AuthenticationScheme);
// Remove the cached details here. If you need to determine
// who's the authenticated user, you can use the identity variable.
// Remove the authentication cookie and return the user to the client application.
return SignOut("ServerCookie", OpenIdConnectServerDefaults.AuthenticationScheme);
}
You can also do something similar directly from the LogoutEndpoint event. Don't forget to call context.HandleResponse() to make sure the request is not intercepted by another middleware.
I am trying to authenticate a user with Azure Mobile Services from within a ASP.NET Web Form (.aspx.cs).
I have provisioned my Mobile Service to authenticate with Facebook using the steps described here: http://azure.microsoft.com/en-us/documentation/articles/mobile-services-windows-store-dotnet-get-started-users/.
This tutorial, however, describes authenticating in a XAML app where popups can appear, but I need to Log the user in within a postback of the web form, where showing a popup is impossible.
According to the docs I can do this by using the LoginAsync() function, like this":
MobileServiceClient client = MyAppsMobileClient.getClient(); //this handles setting the app ID and url
MobileServiceUser user = client.LoginAsync("facebook","");
Now, my problem is the second argument of this function. According to the docs, this is of type JObject, and apparently it is a JSON object I obtain from facebook when I first log in. Now, I can make a simple Login form for the user to enter his facebook ID and password, but I still don't know how to obtain the JObject I need to log in to Mobile Services. Do I need to delve into the Facebook APIs? Is this done using Ajax? Any examples, guides or tutorials on this would be welcome.
You can create a jObject from the data received from Facebook like this:
var token = JObject.FromObject(new
{
access_token = "YOUR TOKEN HERE"
});
This sample was taken from this SO thread:
Azure Mobile Service LoginAsync with Facebook Token is Unauthorized
And here you can read how to obtain an access token from Facebook using JavaScript:
Obtaining an Access Token