I am developing an App that has a server side using Play Framework Scala, and a client side AngularJS.
I want to manage authentication only on the server side because I will have to secure both the API and the application itself and I want to keep the sessions "centralized" on my server.
But since I am not using Play Framework view templating (to keep my client side and my server side independant), I cannot pass the user profile information to the client side as it is done in the examples.
I tried to list my Cache and my Cookie keys on my Angular template but I can't seem to find anything there.
Is there any way I can grab the session information using Angular? having the session requested and managed by Play Framework ? (I cannot find it anywhere on the docs)
Here is how I render my Angular client side front page (Play framework only does the API routing and this front page routing)
def frontPage() = AuthenticatedAction {
request =>
val idToken = request.session.get("idToken").get
val profile = cache.get[JsValue](idToken + "profile").get
Ok.sendFile(content = new File("./public/layout.html"), inline = true).as("text/html")
}
Here is how it is done on the docs example :
def index = AuthenticatedAction { request =>
val idToken = request.session.get("idToken").get
val profile = Cache.getAs[JsValue](idToken + "profile").get
Ok(views.html.user(profile))
}
I would need to get that "profile" across to my template, but I don't want to have scala html templates : I want to keep using pure Angular templates to keep my client / server sides independants (only communicating through an API)
EDIT 21/06/2016: I did not find a way to grab my session information directly from Angular, but I was able to return it by extending my API and I like that solution better ! see https://stackoverflow.com/a/37942787/4884034
You can render it to the client side with:
Ok
.sendFile(content = new File("./public/layout.html"), inline = true).as("text/html")
.withSession(session)
or .withCookies(cookie)
So, thanks to #Simon for pointing me in the right direction.
I am now sending a session after the login :
Ok.sendFile(content = new File("./public/layout.html"), inline = true).as("text/html").withSession("connected" -> profile.toString())
I was not able to get the session directly from Angular, so what I did instead is I updated my API to have an action returning the Session information :
def getSession = Action { request =>
request.session.get("connected").map {
user => Ok(Json.parse(user))
}.getOrElse {
Unauthorized("Oops, you are not connected")
}
}
(in routes :
## USER SESSION
GET /api/session controllers.Callback.getSession
)
That way I can call the API to get my session information on my client side, may it be Angular, a mobile app or any kind of application that reads JSON.
Example of JSON returned :
{"email":"XXX#XXX.com","email_verified":false,"clientID":"MvM2wHRX2rMKp5s3UXXXXXXXX","updated_at":"2016-06-21T10:59:49.730Z","picture":"https://s.gravatar.com/avatar/e91d5ae3XXXXXXXXXXX?s=480&r=pg&d=https%3A%2F%2Fcdn.auth0.com%2Favatars%2Fda.png","user_id":"auth0|5XXXXXXXXX47b1b07d","name":"XXX#XXX.com","nickname":"XXX","identities":[{"user_id":"5767bea338XXXXXX","provider":"auth0","connection":"Username-Password-Authentication","isSocial":false}],"created_at":"2016-06-20T10:00:03.921Z","sub":"auth0|5767beXXXXXXX"}
I hope it will help anyone trying to have a decoupled Play Framework server side from its client side !
Related
I have a logic app with http trigger. I am trying to create a proxy for the logic app using APi management. The issue I am facing is that APi management when calling the Logic App, adds operation name which makes the logic app url invalid.
Example: logic app url: azure/invoke
API manager operation name: pass
Looking at trace logs, URL to call Logic app is:
azure/invoke/pass
I am trying to manually add url to backend service with Blank API design instead of using LogicApp.
API management preserves operation URL template while forwarding request to backend API. You can use rewrite-uri policy to control that behavior. In your scenario try adding <rewrite-uri template="/"/>
Anyone struggling why this is happening. The url in the front end is being passed in to the back end. You can either make it empty, add a policy to trim that off
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.
I have an AngularJS application (using ASP.NET Web API as the backend) that does not require the user to authenticate (the application has no login). I want to make sure that the REST API methods the AngularJS application invokes can only be invoked from the application. I obviously cannot use token based authentication for that.
If doing nothing special the REST API methods can be invoked freely using the browsers address bar or by writing a desktop application that invokes them. The same-origin policy is only regarded if a browser invokes an API method by a HTML page coming from a site having another origin. The REST API is therefore open to the public and easily hackable.
I wonder what I could do to securely restrict the access to the REST API. Any ideas or experience?
Edit 1:
I found an easy solution for my problem: I just check if the host of the URL referrer is the same as the host of the requested URL. Using ASP.NET Web API the code the REST API actions use is:
private bool ApiCallIsAllowed()
{
var request = HttpContext.Current.Request;
return (request.UrlReferrer != null &&
request.UrlReferrer.Host == request.Url.Host);
}
I am just not 100% sure if I always get the URL referrer.
Edit 2: According to this question the URL referrer ist not reliable. Bummer.
use ssh - that's obvious :)
login process should generate token - write it as a cooke - every http request will use it in header
prepare rest interceptor that will read your token and authorize every request
use some Javascript Obfuscator
Don't forget to invalidate session ;).
you can use spring-security or other framework to simplify this process
I'm setting up oauth2 with Salesforce connect using AngularJS. When I attempt the initial GET using $http I get CORS errors - Access-Control-Allow-Origin not allowed for my client. However, using the hack below in my controller function works.
Is there a better way to do this in AngularJs given that I don't have control over the server? My backend is Firebase so it would be great if I could do this through FIrebase like I can for Facebook :
$scope.auth = function () {
var authUrl = $scope.AUTHORIZATION_ENDPOINT +
"?response_type=token" +
"&client_id=" + $scope.CLIENT_ID +
"&redirect_uri=" + "https://www.xyz/";
window.location = authUrl ;
The cors issue happens when make asynchronous call to different server via browser.
So it doesn't appear if the call is made from another server. so you have to use a proxy server which in turn makes a call to your actual server.
You can try the below proxy server which is straightforward.
https://www.npmjs.com/package/cors-anywhere
or you can write your own proxy server which runs on the same domain as your client app and proxies your request to the secured server.
I am currently working on a small project using RESTlet on Google App Engine/Java.
I was searching.. searching.. and couldn't find the exact or understandable solutions for my doubts.
My question is that How am I suppose to implement my own SignIn & SignUp module without using google's UserService or Spring Security??
Is there any actual sample code available??
I mean SignUp part is just a simple JDO insert & select module. let's just say I've done it.
How am I supposed to handle each user's request session and authentication??
I am thinking about using HTTPS on every request.
Any suggestions or help would be really appreciated!
Thanks in advance.
In Restlet, you have security support on both client and server sides. On client side, you can specify security hints using the ChallengeResponse entity. This feature is open and you can specify the authentication type you want. In the following code, I use an http basic authentication based on username / password:
ClientResource cr = new ClientResource(uri);
ChallengeScheme scheme = ChallengeScheme.HTTP_BASIC;
ChallengeResponse authentication = new ChallengeResponse(
scheme, "username", "password");
cr.setChallengeResponse(authentication);
Restlet will automatically build necessary headers in the corresponding request. You can note that Restlet supports a wide range of authentication types through its extensions. I know that some work is done at the moment to support OAuth v2 (see http://wiki.restlet.org/developers/172-restlet/257-restlet/310-restlet.html).
On the server side, you need to secure accesses at routing level using the ChallengeAuthenticator entity, as described below. This can be done within your Restlet application:
public Restlet createInboundRoot() {
Router router = new Router(getContext());
ChallengeAuthenticator guard = new ChallengeAuthenticator(getContext(),
ChallengeScheme.HTTP_BASIC, "realm");
guard.setVerifier(verifier);
guard.setEnroler(enroler);
guard.setNext(router);
return guard;
}
Like for client side, this support is generic and is based on two interfaces that need to be specified on the guard:
The verifier one to check if authentication is successful
The enroler one to fill roles for the authenticated user
You can notice that same security technologies need to be use on both sides...
If you want to manage authentication session for user, you need to implement it by yourself using cookies.
When authentication successes on server side, you can return a cookie containing a security token that allows you checking the user from your database (for example). Some code like below can implement that:
CookieSetting cookie = new CookieSetting(0,
SECURITY_COOKIE_NAME, securityToken);
Series<CookieSetting> cookieSettings = response.getCookieSettings();
cookieSettings.clear();
cookieSettings.add(cookie);
You can extend for example the SecretVerifier class of Restlet to add a test on security data received and add this code when receiving the security cookie.
On client side, you need to add hints for authentication the first time and then re send the security cookie following times, as described below:
ClientResource clientResource = (...)
(...)
Cookie securityCookie = new Cookie(0,
SECURITY_COOKIE_NAME, securityToken);
clientResource.getRequest().getCookies().clear();
clientResource.getRequest().getCookies().add(securityCookie);
Hope it will help you!
Thierry
If you are interested in re-using social accounts, you need to integrate with each one like facebook oauth
And/Or use the app engine authentication via OpenID
Both ways define an API to authenticate a client, you can use the UserService or manage your own state via cookies.