I use an external service for authentication Stamplay ..
To authenticate with username and password, I have to make a post in ${config.host}/auth/v1/local/login
The callback for this post contain the token, so I created a custom authenticator to handle it
Custom Authenticator
export default Base.extend({
tokenEndpoint: `${config.host}/auth/v1/local/login`,
// ... Omited
authenticate(options) {
return new Ember.RSVP.Promise((resolve, reject) => {
Ember.$.ajax({
url: this.tokenEndpoint,
type: 'POST',
data: JSON.stringify({
email: options.email,
password: options.password
}),
contentType: 'application/json;charset=utf-8',
dataType: 'json'
}).then(function (response, status, xhr) {
Ember.run(function () {
resolve({
token: xhr.getResponseHeader('x-stamplay-jwt')
});
});
}, function (xhr) {
Ember.run(function () {
reject(xhr.responseJSON.error);
});
});
});
},
invalidate(data) {
return Ember.RSVP.Promise.resolve(data);
}
});
And everything works fine.. but ...
My problem
For social logins, I need to redirect the user to https://MYAPP.stamplayapp.com/auth/v1/EXTERNAL_SERVICE/connect
EXTERNAL_SERVICE can be.. github, twitter, facebook...
Then, the user is redirect to service page, and after login, the callback will be http://myapp.com/callback?jwt=XYZ
So, how can I capture the token and login the user with this token?
Tell me if I'm wrong, but I think that for Facebook you can use Torii which is working well with simple-auth. Twitter is using Oauth1.0, so it's a bit more complicated in my opinion. But Facebook / Google should be fine.
Basically, Ember will request an AuthorizationCode from Facebook API, then send it to your server. Your server will then ask Facebook API an access_token, and use it to get the user information. Finally, you can load/register your user, generate a JWT token and send it to your Ember app.
But I'm interested to know if you have found a solution for Twitter.
Related
I'm building a separated VueJS/Django app where Django will communicate with the Vue frontend using JSON. In order to be able to use the standard session authentication and django-allauth i will deploy the two apps on the same server and on the same port.
Here is my problem: after i log in from the Vue app using Axios, i don't receive any response but i notice that a session is created on the db, so i'm assuming that i'm getting logged in. But if i try to reach and endpoint that prints request.user.is_authenticatedi get False, and request.user returns Anonymous, so i'm not logged in anymore. How can i solve this?
Here is my Axios code:
bodyFormData.append('login', 'root');
bodyFormData.append('password', 'test');
axios({
method: "post",
url: "http://127.0.0.1:8000/accounts/login/",
data: bodyFormData,
withCredentials: true,
headers: { "Content-Type": "application/json" },
})
.then(function (response) {
//handle success
console.log(response);
})
.catch(function (response) {
//handle error
console.log(response);
});
I think Django-Allauth supports AJAX authentication on its urls, but i don't understand how to make it return something and how can my Vue app stay authenticated once i submit the Axios form. Any advice is welcome!
I just can't wrap my head around how the authentication is done if I use Firebase auth and I wish to connect it to my django rest backend.
I use the getIdTokenResult provided by firebase as such:
async login() {
this.error = null;
try {
const response = await firebase.auth().signInWithEmailAndPassword(this.email, this.password);
const token = await response.user.getIdTokenResult();
/*
No idea if this part below is correct
Should I create a custom django view for this part?
*/
fetch("/account/firebase/", {
method: "POST",
headers: {
"Content-Type": "application/json",
"HTTP_AUTHORIZATION": token.token,
},
body: JSON.stringify({ username: this.email, password: this.password }),
}).then((response) => response.json().then((data) => console.log(data)));
} catch (error) {
this.error = error;
}
},
The only thing I find in the firebase docs is this lackluster two line snippet: https://firebase.google.com/docs/auth/admin/verify-id-tokens#web
where they write
decoded_token = auth.verify_id_token(id_token)
uid = decoded_token['uid']
# wtf, where does this go?
# what do I do with this? Do I put it in a django View?
I found a guide here that connects django rest to firebase: https://www.oscaralsing.com/firebase-authentication-in-django/
But I still don't understand how its all tied together. When am I supposed to call this FirebaseAuthentication. Whenever I try to call the login function I just get a 403 CSRF verification failed. Request aborted.
This whole FirebaseAuthentication class provided by the guide I linked to above - should I add that as a path on the backend?
path("firebase/", FirebaseAuthentication, name="api-firebase"),
Which is the api endpoint my frontend calls?
I m new to loopback and don't know how to do following things in loopback
I want to set access token and other value in a session using middleware for that I found this thing in server folder of loopback
"session": {},
in middleware.json but don't know how to use this because there is not much documentation
I want to condition in session middleware like if I has session value then continue else throw to login page
note i already install this npm install express-session
Could you be a little more specific about what you want? but I'll explain a little bit about how authentification sessions are handled, there are two native ways you treat it all; The first one would be using a more raw reading pulling for modeling of your api and the second would be to use the JWT in aligned with accessToken and Passport.JS.
There are two examples available today with Loopback 3.x
loopback-example-user-management
loopback-example-passport
Basically using the raw reading with app.post('/login', function(req, res) then if your client is successfully authenticated you generate a cookie using your client's accessToken, example res.cookie('access_token', token.id, { signed: true , maxAge: 300000 }); res.set('X-Access-Token', token.id); and finally if you want you can transport the generated token to your pages:
res.render('home', {
email: req.body.email,
accessToken: token.id
});
Now with Passport.JS a middleware is used to secure all your connection and authentication:
app.middleware('session:before', cookieParser(app.get('cookieSecret')));
app.middleware('session', session({
secret: 'Seal Playing Saxophone',
saveUninitialized: true,
resave: true,
}));
passportConfigurator.init();
One of the authenticated page rendering pillar is var ensureLoggedIn = require('connect-ensure-login').ensureLoggedIn; you can use this ensureLoggedIn('/login') to free up your routes:
app.get('/auth/account', ensureLoggedIn('/login'), function(req, res, next) {
res.render('pages/loginProfiles', {
user: req.user,
url: req.url,
});
});
Now if you just want to skip this all and already have your environment set up and just want to create a route to get the accessToken of the logged in client use the template below;
app.get('/session-details', function (req, res) {
var AccessToken = app.models.AccessToken;
AccessToken.findForRequest(req, {}, function (aux, accesstoken) {
// console.log(aux, accesstoken);
if (accesstoken == undefined) {
res.status(401);
res.send({
'Error': 'Unauthorized',
'Message': 'You need to be authenticated to access this endpoint'
});
} else {
var UserModel = app.models.user;
UserModel.findById(accesstoken.userId, function (err, user) {
// show current user logged in your console
console.log(user);
// setup http response
res.status(200);
// if you want to check the json in real time in the browser
res.json(user);
});
}
});
});
I hope I have illuminated your ideas :] I am here to answer your questions.
React-Django application. User signs in by providing username and password through Axios PUT, if correct JWT and username is returned, both are stored in sessionStorage. User is then automatically routed to /home which should populate with information specific to the user.
/home has componentWillMount() that is supposed to GET via Axios the content for /home from the database. Some is static and some is relevant to the user, for example first_name. I'm trying to send the username along with the JWT to retrieve this information but not sure how to.
This is what I have that is working in retrieving static content like the welcome message. Just want to send username along to so I can add logic server-side to retrieve information for this user and send back in the response.
import axios from 'axios';
import { push } from 'react-router-redux';
import { ROOT_URL } from '../../config/config.json';
// Establish the different types
export const WELCOME_MESSAGE = 'welcome_message';
export function getWelcome() {
return function(dispatch) {
axios
.get(
`${ROOT_URL}/api/home/`,
{ headers:
{
'Content-Type': 'application/json',
'Authorization': 'JWT ' + sessionStorage.getItem('token')
}
}
)
.then(response => {
dispatch({
type: WELCOME_MESSAGE,
payload: response.data
});
})
.catch(error => {
console.log("Broke");
});
}
}
Worst case, I just make another function with POST where I know I can send this information easily.
So you want to send the username in GET request method in AXIOS.
You can send the username in URL as the query so that at the backend you can access username from URL query
example:
${ROOT_URL}/api/home?username=rahulrana
This is how you can achieve this through GET method.
through the query in URL is the only way to send information.
Get an [error="unauthorized", error_description="Full authentication
is required to access this resource"] when trying to connect the ember app to oauth2 authenication service.
Any suggestions will be greatly appreciated. I have spend couple of days trying to fix this but to no avail.
here is the code in app.js
Ember.Application.initializer({
name: 'authentication',
initialize: function(container, application) {
Ember.SimpleAuth.Authenticators.OAuth2.reopen({
makeRequest: function(credentials) {
credentials.client_id= 'rsweb-client';
credentials.client_secret= '123456';
credentials.scope='read';
return Ember.$.ajax({
type: "POST",
url: 'http://127.0.0.1:8080/api/oauth/token',
async: false,
data:credentials,
success: function (data, textStatus, xhr){
Ember.run(function(){
resolve({username: data['pl-usr-nickname']});
});
},
error: function (xhr, status, error){
Ember.run(function(){
console.log(xhr.responseText);
});
}
});
}
});
Ember.SimpleAuth.setup(container, application, { // #todo at version 0.1.2 of Ember-simple-auth, add container
crossOriginWhitelist: ['http://127.0.0.1:8080'], // #todo remove when live
// store: Ember.SimpleAuth.Stores.LocalStorage,
authenticationRoute: 'login'
});
}
});
Here is the # The OAuth-secured REST Endpoint
This uses the simple OAuth Resource Owner Password flow.
Here is an example of how to acquired an access_token, and then use that access_token to update an application.
```
curl --noproxy localhost -X POST -vu rsweb-client:123456 http://127.0.0.1:8080/api/oauth/token -H "Accept: application/json" -d "password=password&username=user&grant_type=password&scope=read&client_secret=123456&client_id=rsweb-client"
This returns an token when i access from the command line tool.
But not from the ember app.
Here is the request payload:
Content-Type application/x-www-form-urlencoded; charset=UTF-8
Accept */*
Parameters application/x-www-form-urlencoded
client_id rsweb-client
client_secret 123456
grant_type password
password password
scope read
username user
It looks like your auth server expects the client_id and client_secret as HTTP basic auth credentials while your authenticator sends them in the payload. You'll have to add the Authorization header in the makeRequest method as defined e.g. here: https://www.rfc-editor.org/rfc/rfc2617 which would be a base64-encoding of "rsweb-client:123456".