make custom API call with authentication - ember.js

I am trying to develop an application that should eventually replace an existing (non-Ember) one and provide additional functionality.
For a start, for anything not yet implemented in the new app, I want to redirect users to the existing one, using the latter's single-sign-on capability. The workflow I imagined is this:
User logged in to new (Ember) app clicks link or button there
New app makes an API call to an endpoint that returns an SSO token
New app generated link including SSO token, opens it (in new or same window)
I use ember-simple-auth to authenticate the user for API calls that return user-specific information, using a JSON web token that contains the user id.
For step 2 above I would need to include that token in the API call, but I am at loss how, and even where to implement the call. Do I need an Ember.Route for this (where I could throw in the AuthenticatedRouteMixin)? I would not consider the SSO token to be part of my model, so that does not seem right. Can I get the session's token somehow and include it in a direct ajax call? Should I?

ember-simple-auth provides the SessionService where you can access that information.
My recommendation is to use ember-ajax to make the actual request, and override the ajax service to call the session services authorize method.
Then you need to implement your authorizer to authorize that request.
The detail implementation depends on your authorizer and how you want to include the token in your request. As header, query param, or in the body.

Related

How to implement SSO (single-sign-on) with third party CAS (Central Authentication Service) for a Django-React application?

I'm setting up a Django-React application, with authentication through third party CAS. The process of CAS authentication looks like following:
The web application redirects the user's browser to CAS's login URL with a "service" parameter, for instance https://cas.com/login?service=http://myapp.com.
Once the user has been authenticated by CAS, CAS redirects the authenticated user back to the application, and it will append a parameter named "ticket" to the redirected URL. Its ticket value is the one-time identification of a "service ticket". For instance, http://myapp.com/?ticket=abcdefg.
The application can then connect to the CAS "serviceValidate" endpoint to validate the one-time service ticket. For instance, https://cas.com/serviceValidate?service=http://myapp.com&ticket=abcdefg.
In response, CAS shall return an XML containing the authenticated user id, for instance,
<cas:serviceResponse>
<cas:authenticationSuccess>
<cas:user>johnd</cas:user>
</cas:authenticationSuccess>
</cas:serviceResponse>
I've done some research and found it could be implemented in mainly two ways:
Serve react as part of Django's static content.
Standalone react single page application(SPA) through JWT.
I've tried the first approach and it works, but the problem is that every time I want to test the authentication with React, I need to build the static file first and put them in Django, which is kind of slow. So I would like to try the second approach.
My question is that is there any best practice I could implement for the standalone approach? If I were to implement JWT, is it safe to store the access token in localStorage or cookie?
Many Thanks!

Django REST framework - prevent data access for user view?

In my api, I have a /users endpoint which currently shows (eg address) details of all users currently registered. This needs to be accessed by the (Ember) application (eg to view a user shipping address) but for obvious reasons I can't allow anyone to be able to view the data (whether that be via the browsable api or as plain JSON if we restrict a view to just use the JSONRenderer). I don't think I can use authentication and permissions, since the application needs to log a user in from the front end app (I am using token based authentication) in the first instance. If I use authentication on the user view in Django for instance, I am unable to login from Ember.
Am I missing something?
UPDATE
Hi, I wanted to come back on this.
For authentication on the Ember side I'm using Ember Simple Auth and token based authentication in Django. All is working fine - I can log into the Ember app, and have access to the token.
What I need to be able to do is to access the user; for this I followed the code sample here https://github.com/simplabs/ember-simple-auth/blob/master/guides/managing-current-user.md
I have tested the token based authentication in Postman, using the token for my logged in user - and can access the /users endpoint. (This is returning all users - what I want is for only the user for whom I have the token to be returned but that's for later!).
The question is how to do I pass the (token) header in any Ember requests, eg
this.store.findAll('user') .... etc
This is clearly not happening currently, and I'm not sure how to fix this.
UPDATE
Fixed it. Turns out that the authorize function in my application adapter was not setting the headers, so have changed the code to set the headers explicitly:
authorize(xhr) {
let { access_token } = this.get('session.data.authenticated');
if (isPresent(access_token)) {
xhr.setRequestHeader('Authorization', `Token ${access_token}`);
}
},
headers: computed('session.data.authenticated.token', function () {
const headers = {};
if (this.session.isAuthenticated) {
headers['Authorization'] = `Token ${this.session.data.authenticated.token}`
}
return headers;
})
Ember is framework for creating SPAs. These run in the browser. So for Ember to get the data, you have to send the data to the browser.
The browser is completely under the control of the user. The browser is software that works for them, not for the owner of the website.
Any data you send to the browser, the user can access. Full stop.
If you want to limit which bits of the data the user can read from the API, then you need to write the logic to apply those limits server-side and not depend on the client-side Ember code to filter out the bits you don't want the user to see.
I don't think I can use authentication and permissions, since the application needs to log a user in from the front end app (I am using token based authentication) in the first instance. If I use authentication on the user view in Django for instance, I am unable to login from Ember.
This doesn't really make sense.
Generally, this should happen:
The user enters some credentials into the Ember app
The ember app sends them to an authentication endpoint on the server
The server returns a token
The ember app stores the token
The ember app sends the token when it makes the request for data from the API
The server uses the token to determine which data to send back from the API

Amazon AWS getAttribute() using AWS.config.credentials

I have just started with Amazon Cognito and I want to use it for my web application. I want to develop a stateless app, in which I SignUp/SignIn using Cognito and then using the JWT token in rest of the requests.
I have implemented sign-up and sign-in flow in Node.js using amazon-cognito-identity-js package and then using the JWT token to call a lambda function using aws-sdk. Things are as expected till here.
But now the issue is with different user operations like get attribute, verify attribute, update password etc. as listed #
https://docs.aws.amazon.com/cognito/latest/developerguide/using-amazon-cognito-user-identity-pools-javascript-examples.html
All of these operations require cognitoUser object and in the documentation they are using userPool.getCurrentUser(); expression.
And I have read somewhere that this method returns the last authenticated user. So I think this expression userPool.getCurrentUser(); will cause conflicts. For example if UserB logs in after UserA and UserA tries to update his password, it will not work.
Can someone suggests me what are the possible solutions?
Should I store the cognitoUser object in session at server side ?
[This solution breaks my stateless requirement and I will have to maintain session on server side.]
Is there any way to perform these operations using JWT token ?
Please suggest if you can think of any other better approach to implement Cognito in web app.
Thanks.
We have a stateless app using cognito and lambdas.
The way we have set it up is to not call lambdas directly but to use Api Gateway and lambda-proxy integration.
If you call lambdas directly from your front end code and are using the cognito tokens for authentication then you need to put a lot of logic in each lambda to validate the token, e.g. download the relevant keys, check the signature of the jwt, timestamps, issuer etc. If you use API gateway then you can just create a cognito authorizer and place it in front of your lambdas.
We pass the id_token when making api calls, then the call is validated by the authorizer and the lambda receives all the current attributes set up in the user pool. This means we don't need to make additional calls to get attributes.
For changing the user passwords this can be done from the front-end of the app by calling the cognito api with the access_token if you have allowed it in the user pool client setup.

Django-allauth, JWT, Oauth

I have an AngularJS Single Page Application that uses a Django backend API based on the Django Rest Framework. The API is protected via django-rest-framework-jwt. I would like to use django-allauth for account management and authentication on the server side.
I am just missing one single piece in the flow: How does my Oauth-Token from the client get transferred into a JWT-token? Basically, I would like to do as described here http://blog.wizer.fr/2013/11/angularjs-facebook-with-a-django-rest-api/ based on python-social-auth.
So my question is, how do I implement the ObtainAuthToken class from the link with django-allauth?
There are usually two login flows with social login: client-side ("Javascript SDK") and server-side. If your server needs to be authorised, it's usually a lot easier to go through the server-side flow. And that's also what all-auth does I think (and you didn't mention you use a frontend library like the blogpost you mentioned does).
Now the challenge is to provide the token from the server to the frontend. You would probably load the token in the HTML of the initialisation of the SPA, and then from Angular save the token client side (cookie, localStorage, etc.) so the session isn't lost on a refresh.
If you don't want the user to leave your app, you can open your /accounts/login/ or /accounts/signup/ url in a new window. In that new window they authorise your app, and your server receives the token upon return. There, you will have to generate a JWT token manually, and render that into the template so that javascript can access it. With js in that popup window, you can then communicate with your app that opened the popup and pass it the token – see this SO answer for an example – so it can save it.
Django-allauth provides signals that let you hook into the social login process. In your case, I would recommend subscribing to the allauth.socialaccount.signals.pre_social_login signal. The code will look something like this:
from allauth.socialaccount.signals import pre_social_login
#receiver(pre_social_login)
def create_jwt_token(sender, request, sociallogin, **kwargs):
# dig into the sociallogin object to find the new access token.
We used hello.js for O-Auth at the company I worked at.
You provide a shim on the Python end and get the refresh token and whatever other data needed once the user connects their social account.
We redirect them via Django to the page they attempted to access from their OAuth provider's page.
Each user still has their own email account which is needed for the JWT, but you could assume that whatever email is in the scope of their social account is their email then use django's functionality to create new users: User.objects.create(email=emailStringFromOauthData) etc.

Emberjs and Simple Auth for any $.ajax

I am doing an $.ajax post command and i currently have an authenticated session on the client side. I am trying to figure out how to add the token to the ajax call (as on the server i check the token to see if it matches in my local database. How is it possible to use that same auth token in a generic ajax call ?
Thanks
You add the token as a request header in your authorizer.
To do this, either use one of the including solutions (if you're using the corresponding backend), or implement your own custom authorizer.
If you have to write your own, you can look at the devise authorizer's authorize method for an example of how to add the header.