I'm attempting to integrate the 'Nuxt Auth Module' into my Nuxt App.
https://auth.nuxtjs.org/
I have configured my Proxy & Auth Modules and have setup the 'Local Strategy'.
https://auth.nuxtjs.org/schemes/local.html
My 'Login' endpoint works fine, and I set the 'propertyName' to 'access_token' as that is where the value for my token lives. I see 'Vuex' update my 'LoggedIn' status to true and I can also see the Token Response in the 'Network' tab of Chrome.
However I'm really struggling to understand how the 'User' endpoint works.
The example given:
auth: {
strategies: {
local: {
endpoints: {
login: { url: '/api/auth/login', method: 'post', propertyName: 'token' },
logout: { url: '/api/auth/logout', method: 'post' },
user: { url: '/api/auth/user', method: 'get', propertyName: 'user' }
},
tokenRequired: true,
tokenType: 'bearer'
}
}
}
The above is pretty much identical to mine, how does the 'User' endpoint, know which user is logged in?
I am using a third-party system for my authentication as I'm integrating an application into the third-party system. Their 'User' endpoint for REST requires an 'ID' or 'UserName' to return details about a particular user.
My 'Login' response contains 'UserName' which I could use to call the subsequent User endpoint (If I knew how).
Does anyone know how the User endpoint works? Essentially I need to call something like this:
user: {
url: '/users/${userId}',
method: 'get',
propertyName: 'data'
}
Faced to this problem, too.
My solution:
Set user property of auth endpoint to false
auth: {
strategies: {
local: {
endpoints: {
// login api
login: {
url: '/api/v1/users/login',
method: 'post',
propertyName: 'token'
},
// logout api
logout: {
url: '/api/v1/users/logout',
method: 'post'
},
user: false // setting user fetch api to false
},
redirect: {
login: '/login',
logout: '/login',
callback: '/login',
home: '/'
},
}
}
},
After loginWith() You can use function setUniversal(key, value, isJson) to save fetched user and get it with function getUniversal(key)
async login(user) {
await this.$auth.loginWith('local', {
data: user
}).then(res => {
let user = res.data.data.user // getting user (yours can be different)
this.$auth.$storage.setUniversal('user', user, true) // setting user in Vuex, cookies and localstorage
user = this.$auth.$storage.getUniversal('user') // getting user (you can use it anywhere in your app)
console.log(user) // checking user
this.$router.push('/') // redirecting after login
}).catch(err => {
console.log(err.response)
})
}
That's all, you have your user in vuex, cookies, and localstorage you can get it in computed like this:
computed: {
user() {
return this.$auth.$storage.getUniversal('user');
}
}
P.S: to logout, use logout() function, and in the callback use this.$auth.$storage.removeUniversal('user') to remove it from everywhere
Related
I am trying to make POST request in Cypress in order to perform auto login and redirect to dashboard page.
Here is the
Website link : https://admin-demo.nopcommerce.com
Error
The Code I have added to perform auto login is
Cypress.Commands.add('autologin', () => {
cy.clearCookies();
let options = {
method: 'POST',
url: 'https://admin-demo.nopcommerce.com/login?returnurl=%2Fadmin%2F',
headers: {
'authority': 'admin-demo.nopcommerce.com',
'Content-Type': 'application/x-www-form-urlencoded',
'origin': 'https://admin-demo.nopcommerce.com',
},
body: {
Email: 'admin#yourstore.com',
Password: 'admin',
__RequestVerificationToken:
'CfDJ8EoKK8bdbeVGtbyUmFkZjVXayQ00hwk5B6a1cPRgR3HvKKdGXLUNrX2hLPzPqPWV-RDY0zU-qaOalPnt9-fPC7xnshZqx1MMB_2aKitiCzSmm4CstnsQSi3YfrYGFzMVhck6tI02IznyqRUto2akvAA',
RememberMe: false,
},
};
cy.request(options).then(response => {
console.log(response);
});
});
Cypress.Commands.add('login', () => {
cy.autologin();
cy.visit('https://admin-demo.nopcommerce.com');
cy.get('#nopSideBarPusher').should('be.visible').click();
cy.get('#nopSideBarPusher').should('be.visible').click();
cy.clearCookies();
cy.get('.navbar-collapse .nav-link')
.eq(1)
.then(val => {
cy.get(val).click();
});
});
The purpose of __RequestVerificationToken is that it changes with every page refresh, so if you added this one string in there, it does make sense the server refused the whole request. There's a limited number of valid tokens at a given time, this one will likely be invalid by the time you're sending the request.
I'm trying to use nuxt-auth module, my settings for this module is
auth: {
cookie: false,
plugins: ['~/plugins/api.js'],
redirect: {
logout: '/login',
login: '/',
home: false
},
strategies: {
local: {
scheme: 'refresh',
token: {
property: 'token',
maxAge: 3600
},
refreshToken: {
property: 'refresh_token',
data: 'refresh_token',
maxAge: 60 * 60 * 24 * 30
},
user: {
property: 'userDetail'
},
endpoints: {
login: { url: 'http://localhost:8085/api/login_check', method: 'post', propertyName: 'token' },
refresh: { url: 'http://localhost:8085/api/token/refresh', method: 'post', propertyName: 'refresh_token' },
logout: false,
user: { url: 'http://localhost:8085/api/user/fetchactive', method: 'get' }
},
tokenRequired: true
}
}
}
My "fetchactive" API returns a JSON containing a property "userDetail" which is a string containing the email address, (I also tried to make userDetail an object but with no luck).
e.g.
{"userDetail":{"email":"my#email.test"}}
Nuxt auth keeps telling me that "User Data response does not contain field userDetail".
I also tried to set "property" to false, but Nuxt auth in that cases looks for a field named "false"...
I just can't get it to work.
Anyone can help?
using this configuration in the nuxt.config.js file worked for me
auth: {
strategies: {
local: {
user: {
property: ''
},
//other configs
}
}
//other configs
}
It's happened due to the fact that auth.user endpoint search for 'data' object by default in the response but I does not exist there, as You have Your own response object key, not contained in 'data:{...}
try to add propertyName as in example in auth.user
endpoints: {
user: { url: 'http://localhost:8085/api/user/fetchactive', method: 'get', propertyName: '' }
}
}
I have a project with Cloud Firestore as database. Now I want to update the data in one document using the fetch method. My Cloud Firestore stucture is the following:
Logging (Collection)
[userID] (Document)
Notifications (Collection)
[notificationID] (Document)
active: "true"
type: "T1"
And I use the fetch call below:
fetch("https://firestore.googleapis.com/v1/projects/[ID]/databases/(default)/documents/Logging/[userID]
+"/Notifications/[notificationID]?updateMask.fieldPaths=active", {
method: 'PATCH',
body: JSON.stringify({
"active": "false"
}),
headers: {
Authorization: 'Bearer ' + idToken,
'Content-Type': 'application/json'
}
}).then( function(response){
console.log(response);
response.json().then(function(data){
console.log(data);
});
}).catch(error => {
console.log(error);
});
Executing the fetch method I'm running in an error with message
"Invalid JSON payload received. Unknown name "active" at 'document': Cannot find field."
How can I update the existing fields of a document of Firestore with the REST API? Can anyone help me out? I've tried a lot of different "urls" and methods, but nothing works for me.
As explained in the Firestore REST API doc, You need to pass an object of type Document in the body, as follows:
{
method: 'PATCH',
body: JSON.stringify({
fields: {
active: {
stringValue: 'false',
},
},
}),
}
I made the assumption that your active field is of type String (since you do "active": "false"). If it is of type Boolean, you need to use a booleanValue property instead, as follows. See this doc for more details.
{
method: 'PATCH',
body: JSON.stringify({
fields: {
active: {
booleanValue: false,
},
},
}),
}
The login/logout/middleware etc themselves work, but I don't seem to have control over the token. I'm trying to save JWT in Vuex store after logging in, but the token is only saved in a cookie and localStorage. From documentation I understand that support for auth in Vuex is added automatically. I didn't define tokenRequired and tokenType in config as according to documentation they are needed for cookie based flow (also adding them did not change anything).
nuxt.config.js
modules: [
'#nuxtjs/axios',
'#nuxtjs/auth'
],
axios: {
baseURL: 'https://api.example.com/'
},
router: {
middleware: ['auth']
},
auth: {
strategies: {
local: {
endpoints: {
login: { url: 'login', method: 'post', propertyName: 'token' },
logout: { url: 'logout', method: 'post' },
user: false
}
}
},
redirect: {
login: '/login',
logout: '/',
callback: '/login',
home: '/'
}
},
login function
await this.$axios.post('authenticate', {
email: this.email,
password: this.password
}).then(response => {
if (response.success === 'true') {
this.$auth.setUserToken(response.token)
} else {
//alert invalid login
}
}).catch(error => {
//alert server error
});
Now when I successfully log in and look at $auth.$state it returns
{ "user": {}, "loggedIn": true, "strategy": "local" }
I expect the token to also be saved in $auth.
I also looked at a question with similar title, but their solution does not work for me, as I am using user: false.
I looked at auth-module's default.js file and tried the default values in my nuxt.config.js. After adding the default into my configuration it started working. So now I was able to disable the cookies and localStorage, while saving JWT into store only.
auth: {
strategies: {
local: {
endpoints: {
login: { url: 'login', method: 'post', propertyName: 'token' },
logout: { url: 'logout', method: 'post' },
user: false
}
}
},
redirect: {
login: '/login',
logout: '/',
callback: '/login',
home: '/'
},
cookie: false,
localStorage: false,
token: {
prefix: 'token.'
},
},
And $auth.$state returns
{ "user": {}, "loggedIn": true, "strategy": "local", "token.local": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c" }
If anyone has an explanation why the default value did not work and why I had to include it in my configuration, please let me know. I assume for some reason they have disabled the Vuex saving by default? Even though the documentation states what can be interpreted as by default token is saved in three locations.
Auth tokens are stored in various storage providers (cookie, localStorage, vuex)
I have problem with using commit like is described here. Probably problem is in that I use export default new Vuex.Store instead export const store = new Vuex.Store. But when I change this I have problem from this topic.
Here is my JS file, where I use Vuex and I want to call commit:
actions: {
signUserIn(payload) {
payload.password;
var params = new URLSearchParams();
params.append("grant_type", "password");
params.append("username", "admin");
params.append("password", "adminPassword");
axios({
method: "post",
url: "http://localhost:8090/oauth/token",
auth: { username: "my-trusted-client", password: "secret" },
headers: {
"Content-type": "application/x-www-form-urlencoded; charset=utf-8"
},
data: params
}).then(function(response) {
const user = {
login: payload.username
};
localStorage.setItem("access_token", response.data.access_token);
this.commit("setUser", user);
});
}
},
Curently when I run this and I try call signUserIn I have this error in console: TypeError: Cannot read property 'commmit' of undefined
I don't have idea what can I type in google in this case.
I believe you have mistyped. It should be commit and not commmit.
EDIT: Seeing the file, please try using arrow functions instead.
axios({
method: "post",
url: "http://localhost:8090/oauth/token",
auth: { username: "my-trusted-client", password: "secret" },
headers: {
"Content-type": "application/x-www-form-urlencoded; charset=utf-8"
},
data: params
}).then(response => {
const user = {
login: payload.username
};
localStorage.setItem("access_token", response.data.access_token);
this.commit("setUser", user);
});
This is because you will lose the context of this without it. With arrow functions, this remains the this from the outer context. Also, not sure if you need this in this particular case, but try with or without it. ( I said this too many times )
Note the signature of your action method is incorrect. The Vuex docs show that the action method takes the Vuex context (which contains the commit method) as the first parameter and the payload second:
// signUserIn(payload) { // DON'T DO THIS
signUserIn(context, payload) {
With your current code, you'll notice that payload.username and payload.password are undefined.
demo of your action with the bug
Your action method should look like this:
actions: {
signUserIn(context, payload) {
axios.post().then(response => {
context.commit('foo', foo);
});
}
}
demo of fix