How do I verify the ID token with Firebase and Django Rest? - django

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?

Related

Django - why am i not authenticated after logging in from Axios/AJAX?

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!

CSRF_Token in POST method using Vue.js and Django Rest Framework

I'm trying to send a POST request from a Vue.js template to my API created with Django.
When sending I get a 403 CSRF token missing or incorrect error. Since I separated the front and the back, I don't have a view with {csrf_token} on the Django side.
How do I send my form?
I tried some exemples on the web using cookies but i'm beginners and need more explaination about the POST subject and CSRF
I have a Djano View (and urls associated) juste like this :
def get_csrf_token(request):
token = get_token(request)
return JsonResponse({'token': token})
Whe i'm requesting the url, obtained the JSON with the token.
And on the Front side i'm using this method to get the Token :
getToken: function() {
this.loading = true;
this.$http.get('/qualite/get-token/')
.then((response) => {
this.token =response.data;
this.loading = false;
})
.catch((err) => {
this.loading = false;
console.log(err);
})
},
addNc: function() {
let headers = {
'Content-Type': 'application/json;charset=utf-8'
};
if(this.token !== '') {
headers['HTTP_X-XSRF-TOKEN'] = this.token
}
this.loading = true;
this.$http.post('/qualite/api/nc/',this.newNc, {headers: headers})
.then((response) => {
this.loading = false;
})
.catch((err) => {
this.loading = false;
console.log(err)
})
},
For the CSRF you get by default after user login aside with the session, if you're using SessionAuthentication (It's the default authentication used in DRF).
You have to send it with each request in the header, you can refer the this link to know more about the header sent, as it's name is changed and can be configured.
Note also that in the settings you have to make sure that CSRF_COOKIE_HTTPONLY is set to False (which is the default), to be able to read it from the client side JS.
Another path would be removing CSRF enforcement per requests (But it's highly not recommended for security concerns), you can find more about this in the answer here.
Use a Token-based authentification.
Same issue i was encountered with,
the problem was, i had used Class based view and at the time of registered the url i forget to mention as_view() with class Name.
ex:- class PostData(APIView)
before :- path('post_data', PostData)
after correction:- path('post_data', PostData.as_view())

Vuejs error 401 Unauthorized from DRF api

Vue Js error (401 Unauthorized)
Vue Js Error: 401 Image
Software Used-
DRF
Vuejs
while calling DRF api in Vue js (using axios) unbale to get data.
below code in App.vue
export default {
name: 'App',
components: {
'Header': Header,
'Footer': Footer,
'Navbar': Navbar
},
data () {
return {
info: []
}
},
mounted () {
var self = this
axios.get('http://127.0.0.1:8000/management/api/list/')
.then(function (res) {
self.info = res.data
console.log('Data: ', res.data)
})
.catch(function (error) {
console.log('Error: ', error)
})
}
You are requesting to an API which is protected and need authorization credentials to be available.
If you are using DRF token-management systems, you should first get a token from proper API endpoint. then pass this token via Authorization header in request.
For example if you are using jwt token management system in django, then you should send requests like this:
axios.get('http://127.0.0.1:8000/management/api/list/', { Authorization: `jwt ${token}`})
.then(function (res) {
self.info = res.data
console.log('Data: ', res.data)
})
.catch(function (error) {
console.log('Error: ', error)
})
Remember it really depends on your Authentication backend you are using. So if you can give more details about how you implemented your django DRF APIs, I guess we all can help you much better.

how to use session in loopback using middlewre

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.

Authenticate user with external url, Ember Simple Auth after callback with token

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.