Getting external Token into my Angular application - angularjs

My http server framework is serving a static (Angular) SPA.
To authenticate users, they will need to enter their email adress and submit it. They receive a link per email in the form of https://www.somedomain.com/?token=123456789 (inspired by passwordless.net). For later accesses, the token will be stored with localStorage.
My problem is: I have no solid idea how the SPA can learn about that token. Of course, the user may copy&paste that token. Or I can embed that token within the served HTML, but I don't see that being very elegant or even fast, and possible not very secure either.
Is there a simple way to do this I'm missing?

If you are using '$location', then you can simply parse the '$location.url()' and get the token.
If you are using the '$routeProvider', then you can define the routeProvider configuration like this:
$routeProvider.when('/reset_password/:token', { /*controller and template conf here*/ })
And in your controller:
var theToken = $routeParams.token;

Related

Parsing Oauth 2.0 return parameters in angular-ui-router

I'm attempting to authenticate a user using Google's Oauth 2.0 API. When my app HREF's to the Google authentication page, it successfully passes information back to my AngularJS app. However, I'm not sure how best to handle the returned URL-encoded data.
This is the format it is returned as:
#access_token=...
&token_type=Bearer
&expires_in=3600
My main problem is that this string begins with # instead of ? as is traditionally done with URL encoded parameters.
In my stateProvider config, I've implemented the callback state as such:
.state 'auth.googlecallback',
url: '/googlecallback/#{accessToken}&token_type={tokenType}&expires_in={expiresIn}'
templateUrl: 'views/auth/googlecallback.html'
controller: 'GoogleCallbackCtrl as gVm'
The above URL is an example of what I have tried. When the url is simply /googlecallback/, the page loads successfully, even when navigated to using the Google Oauth link. But the moment I had the # symbol, the state breaks and I can't parse the state params for the data inside.
I've looked into using the angular-oauth library on GitHub, but it hasn't been updated in 2 years, and it doesn't appear to allow Oauth authentication for more than just Google (I want to use Facebook and Google).
What is the correct way to handle the the Oauth URL data in angular-ui-router?
To be frank, I don't think this will actually answer your question, but I was helping some friends with this earlier today. They were unable to handle the URI via the ui-router. Instead, they had to delegate parsing the parameters and making the appropriate request to their view controller. Using the Angular $location service and some remapping functions, we were able to get the parameters out of the # query syntax into a hash that he was able to push back to the server in his request. The code looked similarly to the following:
var paramsArray = $location.hash().split('&')
var payload = {};
angular.forEach(paramsArray, function (param) {
var arr = param.split('='),
key = param[0],
value = param[1];
payload[key] = value;
});
This could absolutely be simplified but this was what he was trying to accomplish for his strategy.
That all being said, I'm personally not a fan of trying to accomplish OAuth strategy on the client. You have private keys that usually need to get exchanged to complete the full handshake. If possible, it would be best if you did the following:
Redirect the client to the appropriate OAuth path
Have the redirect go to a server endpoint that can process the oauth request and complete the handshake.
Have the server endpoint that the oauth request redirected to, redirect to your success landing page with any additional response
objects required by your application.
Doing this would protect your private keys and most web frameworks have modules/packages/gems/plugins/etc. for implementing oauth for all the mainstream providers. Hope this helps you in the right direction.

authorisation and login control in an Angular app

So for the past few months I have been developing the 'login functionality' of my Angular apps like this. The user logs in and if the credentials are correct, the REST API returns a token. I take that token and store it as a cookie:
$cookies.put('authorisation', data['token']);
Whenever I call the $http service, I submit the authorisation cookie as a header and it authorises the http request. Then on the controller of each view I add:
if (!$cookies.get('authorisation')) {
$location.path('/login');
}
So if the cookie doesn't exist, the user is automatically kicked to the login screen.
This has worked for me just fine up until now but I can't help but feel that it is not the 'correct' way of doing things. Could anyone shed a little light on what the best practice method for this could be? And perhaps why what I'm doing is 'wrong'?
Are you familiar with Angular $http Interceptors:
https://docs.angularjs.org/api/ng/service/$http#interceptors
You could use the request interceptor to have your authorization checked before each $http request.
If you do this you also have to integrate a custom Flag on each $http config object (e.g. skipAuthorization) in order to allow the user to perform Requests without being logged in (useful for actually logging in ;-))
#AzzyDude to your comment:
I'm using ui-router to do the navigation inside of my Angular 1.6.X Application.
You can either integrate own config-properties on the states (isGuestState) or if its a closed application such as mine, hard-coded in a $stateChange event, like this:

Integrating Laravel, Facebook and Angular with token-based-authentication

My use case:
User is already logged in automatically server side using Facebook with laravel and Socialite.
I check if the user exists in the db and if not create it and log them into laravel.
Then I need to start an Angular app and make sure they are logged in with Laravel / Facebook.
After reading this article, it looks like this token based approach is what I should take.
In the tutorial you serve a login form with Angular, and then pass the email and password to an authenticate controller (Laravel), which returns a token (create by JWT-Auth).
Once the token is in Angular all is well, my problem is that I want to get the token directly into Angular without a login form since the user is already logged in as mention above.
I'm wondering if I could just output the token in markup somewhere and then pick it up from Angular or would that somehow be a security risk? I guess people will only be able to view source and see their own token?
If this is the wrong way to do this, then how should I do it? Do I need to authenticate with Facebook with Javascript, and then create a new laravel user with ajax?
Thanks so much!
One approach you could take is to add something to your .config block that checks for the presence of a JWT in local storage and if there isn't one there, makes a request to the API to see if the user is logged in on the Laravel side. If the user is logged in, a JWT is returned which can be picked up and saved in local storage. Since the .config block is run when the Angular app loads, this will only happen once, which is probably what you're looking for.
Here's what that might look like. First the Laravel side:
// AuthenticateController.php
...
// Simulates a user being logged in on the Laravel side through something
// other than credentials sent from the front-end. Obviously you would use
// Socialite
public function authenticate()
{
$user = User::find(1);
$token = JWTAuth::fromUser(1);
return response()->json(compact('token'));
}
...
Then the Angular:
// app.js
...
.run(function($rootScope, $state, $auth) {
if(!$auth.isAuthenticated()) {
// No credentials provided because the user is already logged in on the server
$auth.login().then(function() {
$state.go('users');
}
}
$rootScope.$on('$stateChangeStart', function(event, toState) {
...
This would just run when the Angular app loads, which will be after your user has logged in with Socialite. It's essentially just checking whether there is a user logged in on the back end and if so, the token is retrieved. It's a bit hacky and the interface isn't obvious, so it might not be the best solution.
You would need to arrange your authenticate controller on the Laravel side such that it returns the token if the user has logged in via socialite or require credentials if he/she hasn't (which is the traditional login).
You could also look at this approach to see if it works for you: https://github.com/barooney/jot-bot/tree/socialite
Let me know if that works out!

angularJS login connect to API backend

I've found alot of text explaining this but i haven't quite found what i'm looking for. I'm hoping someone can point me in the right direction. I am building an Angular App that communicates with a RoR back-end. On the back-end there is a basic authentication with username and password. For the moment i've hardcoded the username and password into my app.js. I'm using Restangular so i set it up like so:
var authenticationToken = btoa('username,password');
.config(function (RestangularProvider) {
RestangularProvider.setDefaultHeaders({Authorization: 'Basic ' + authenticationToken});
}
But what I would like is for users to have to login when they open the app with username and password. So that my app can use those to send requests to the backend. I have no real idea how to set this up properly.
update
I figured out my problem. I'm using default headers, while I should be using individual headers. Which i can just set in my service call.
All you need to do is create a text input in Angular. Follow the example in the Angular documentation. Then in your controller/directive (whatever scope you store the username and password) just make the authentication call like you did in your question.

Adding Custom Header in AngularJs upon bootstrapping

Suppose I have an angular app called chococalateApp that depends on 3 other modules, namely Product, Sales and LogIn.
Now, my app is building on RESTful API. Upon successful login, the server will respond by sending back an authentication token. I would like to append this token as a custom header X-AUTH whenever $http services are used. Since all my REST API requires the auth token, I would need to append this header in every $http request. This is doable by configuring the $httpProvider, as shown below:
angular.module('chocolateApp',['Product','Sales','Login'])
.config(['$httpProvider', function($httpProvider){
$httpProvider.defaults.headers.common['X-AUTH'] = 'randomkeybyserver'
}
])
My question is, can I inject the value of the auth-token AFTER the module has been bootstrapped?
For example, I have a service in LogIn module that is able to do the authentication, and retrieved the required token. How do I pass the token back to my main chocolateApp module and configure it? Will this result in circular dependency, or is it that my understanding of DI is wrong here?
If this is not achievable, how should this be designed?
You can do it from your Login service after authentication and it will be available across your app.
login: function(...) {
$http.post(...).then(function(response) {
$http.defaults.headers.common['X-AUTH'] = response.data.randomkeybyserver;
});
}

Resources