Version 4.1.9 throws an error: "name": "ApplicationError", "message": "Email already taken" via Postman - strapi

My System information
Node.js version: v16.13.0
NPM version: 8.1.0
Strapi version: 4.1.9
Database: Postgres
Operating system: MacOS
The Issue
I recently setup an instance of Strapi and Postgres via railway (https://railway.app), and tried making a few request to test the api. Upon making POST request to fetch/ update a user that was originally setup through Strapi admin, I am getting an Email already taken 404 error message.
Screenshots
https://freeimage.host/i/HCvcw0P
Steps to reproduce the behavior
Configured user Content-Type by adding a user_role field via Strapi admin (Note that this is not meant to replace the default Strapi user role).
Saved the file, and the entry was successfully saved in the database.
Made a GET Request to https://my-railway-url/api/users to retrieve ALL USERS successfully.
I made a Post request to https://my-railway-url/api/auth/local to get user info along with the JWT token
Received a JWT token along with user information.
Copied the JWT Token and made another POST request - with body set to JSON, entered info to update the existing user
Got an error Email already taken
Expected behavior
User information updated with the new entries.

the strapi user-permissions plugin, has it's own logic of controllers, with would not be the same as standard content-type api's
to use it you have following routes:
// LOGIN
url: `api/auth/local`
method: POST
body: {
identifier: string
password: string
}
// ME get current authenticated user
url: `api/users/me` // you can add '?populate=*' here
method: GET
// UPDATE USER
url: `api/users/:id` // you can add '?populate=*' here
method: POST
body: {
...data // < user data
}
seems ?id=3 is invalid in your query, should be /api/users/3

Related

Retrieving a trusted client token within a Keycloak addon (SPI)

As part of our effort to be GDPR compliant, I’m trying to extend our Keycloak server with some custom functionality, to be triggered when a user is removed:
sending a confirmation message to a Slack channel
sending a HTTP request to another service we built, to delete any assets that user might have created there
The first one was easy. It's implemented as a SPI event listener, following this example:
#Override
public void postInit(KeycloakSessionFactory keycloakSessionFactory) {
keycloakSessionFactory.register(
(event) -> {
// the user is available via event.getUser()
if (event instanceof UserModel.UserRemovedEvent){
userRemovedMessageHandler.handleUserRemoveEvent(session, (UserRemovedEvent) event);
LOG.debug("User removed event happened for user: " + ((UserRemovedEvent) event).getUser().getId());
}
});
}
But I'm stuck on the second task (sending the HTTP request). The other service is set up to require a trusted client token, using a designated Keycloak Client and scope. The equivalent POST request to auth/realms/{realm}/protocol/openid-connect/token is done with these parameters:
grant_type: password
username: {user that is about to be deleted}
password: {user password}
client_id: {the specific client}
client_secret: {that client's secret}
scope: usersets
I can’t find out how to do that from within the SPI code. I can retrieve a regular Access Token (as described in this other SO post):
private String getAccessToken(KeycloakSession session, UserModel deleteUser) {
KeycloakContext keycloakContext = session.getContext();
AccessToken token = new AccessToken();
token.subject(deleteUser.getId());
token.issuer(Urls.realmIssuer(keycloakContext.getUri().getBaseUri(), keycloakContext.getRealm().getName()));
token.issuedNow();
token.expiration((int) (token.getIat() + 60L)); //Lifetime of 60 seconds
KeyWrapper key = session.keys().getActiveKey(keycloakContext.getRealm(), KeyUse.SIG, "RS256");
return new JWSBuilder().kid(key.getKid()).type("JWT").jsonContent(token).sign(
new AsymmetricSignatureSignerContext(key));
}
but that's not the token I need. In order to retrieve the required trusted client token I’d need the internal Keycloak / SPI-equivalent of the above POST request, but I can’t figure out how to do that or where to look.
Besides, I'm not sure if it is even possible to retrieve a trusted client token for a user that is in the process of being deleted. In other words, I don’t know if the UserRemovedEvent is fired before, during or after the user is actually deleted, or if Keycloak waits until any custom EventHandlers have finished running.
(In order to figure that out, I'll try if it is possible to retrieve that token using a regular http POST request from within the add-on code, but I have no idea if it's possible to connect to Keycloak like that from inside. I'll update the question if that works.)
I'd greatly appreciate any suggestion!
(I also asked this in the Keycloak discourse group here but it looks as if it will remain unanswered there)

Create new Parse.Session programmatically for a user, without their password

I'm working on a existing Parse server, and I am currently adding an OAuth system, so that external apps can connect in the name of Parse.User.
I created different classes for codes and tokens, and now my external apps can send requests with an accessToken, corresponding to their application and user (who granted access).
I'm looking for a way to inform the Parse server that the "logged in user" in requests is the end user that authorized the OAuth application. For this, I have created an express middleware handling request before the Parse server middleware, extracting the access token from the request, getting the correct User and Application, and then I wanted to create a Parse.Session programmatically, get the token, and set it in the request as x-parse-session-token. This way, the next handler, Parse, would treat the request as authenticated and performed by the end user.
My problem here is that I cannot find a way to create a session programmatically, I'm aware of the Parse.User.logIn, but that works only with a password.
I've tried the following:
const oAuthSession = await new Parse.Session().save({
user: user // user got from Parse.Query(Parse.User) with masterKey
}, { useMasterKey: true })
But get a Cannot modify readonly attribute user error.
Any hidden method to programmatically create a Parse.Session without a password ?
As pointed out by #DaviMacêdo in the community forum: https://community.parseplatform.org/t/create-new-parse-session-programmatically-for-a-user-without-their-password/1751
We can inject the user directly in the request field, and it will be picked up by Parse: https://github.com/parse-community/parse-server/blob/f6a41729a7a3adc6bd5310cefb3458835b4abb58/src/middlewares.js#L199
const user = await new Parse.Query(Parse.User).get(‘idOfUser’);
req.userFromJWT = user;

Failed To authenticate to specific firebase api project?

the project that I am trying to automate is This.
Manual Logged in
When I click on Google logged-in it will redirect to manual login.
after I logged in successfully I can see there Post method
Request URL: https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyAssertion?key=AIzaSyDF-qMBES2pwjDAzWRRsu-FiAxZgJsBuIk
Request Method: POST
with the body
requestUri: "FirebaseappURL"
returnIdpCredential: true
returnSecureToken: true
sessionId: "SessionID???"
after that, it generates a Large respond
context: ""
displayName.
emailverified.
expiresIn:3600
federatedId:...
firstName:.
fullName:.
idToken: <Token>
kind: "identitytoolkit#VerifyAssertionResponse"
lastName: ...
localId: <ID>
oauthAccessToken: <Token>
oauthExpireIn: 3600
oauthIdToken: <Token>
photoUrl: <url>
providerId: "google.com"
rawUserInfo: <long json>
refreshToken: <token>
I want to simulate it with post request with the postman
after that, I will transfer it to Script
What I tried
Google API Config
I went to Google DashBoard Create Project.
Then I go to the OAuth consent screen and add my user as test users.
Add all the Clawee sites as authorizes.
Then I Went to Credentials and add Oauth 2.0 Client ID's of the Desktop client
and got his ClientID and SecretID
Now from postman, I went to
https://accounts.google.com/o/oauth2/v2/auth?client_id=<ClientID>.apps.googleusercontent.com&response_type=code&scope=openid%20email&access_type=offline&redirect_uri=urn:ietf:wg:oauth:2.0:oob
I got my auth-code
now I send a request to
https://oauth2.googleapis.com/token
with params clientid,secretId,authCode,grant_type
and get my Access Token + Refress Token
Now to check that, I navigate to
https://www.googleapis.com/oauth2/v3/userinfo?access_token="
I got My User Info... It works
Now I tried to use that Access Token
To login to Firebase app as they did
but because I using my Own token and not a manual login
I read about the "signInWithIdp" or "verifyCustomToken"
And I tried
with 'postBody': 'access_token=[My_Token]&providerId=google.com' or
token: [My_Token]
Both Failed...
What am I doing wrong?

Passing accessToken from frontend to PHP API

I've been trying to get authentication working (described below) in my laravel application, following these two tutorials:
https://auth0.com/docs/quickstart/webapp/laravel/01-login
https://auth0.com/docs/quickstart/backend/laravel/01-authorization
On the frontend (angular app):
User clicks log in button and taken to auth0 login page
The user logs in and is redirected back to the callback with the accessToken
The access token is stored on the frontend and passed to Laravel API each request.
On the backend:
User makes a request to my http://localhost/api/route passing the accessToken in the authorisation header
Laravel validates the user is logged in and valid.
Laravel allows access to that route
It works to an extend, but when I try to use postman to access the protected route by passing the accessToken I get the error:
"message": "We can't trust on a token issued by: https://myprojectname.au.auth0.com/."
Is my workflow correct? What am I missing?
Thanks!
Just in case if somebody facing with the same issue. The authorized_iss must contain a trailing slash.
In the laravel-auth0.php file the field,
'authorized_issuers' => 'https://myprojectname.au.auth0.com/'
should be in this form.

Where does request.user come from in Parse Server

I'm trying to port my Parse.com app to Parse server.
According to the Parse migration guide, Parse.User.current() can no longer be used and instead you should fetch the current user via 'request.user'.
However, request.user is always undefined for me.
For example, when I successfully login a user and then redirect to another path (/mypath), the incoming request at mypath does not contain a user object.
Parse.User.logIn(username, password, {
success: function(user) {
res.redirect('/mypath');
}
})
// Index of the /mypath controller
exports.index = function(request, response) {
// request.user is undefined here
}
How do I work with the active user after I logged in sucessfully?
I think I figured it out.
When working in Cloud Code there is no magic request.user. Rather when logging in you need to manually store the user info in the current session. In the Parse.com days this would've been managed by the parse-express-cookie-session middleware. This is explained in the cloud code guide. With Parse-Server you can insert your own middleware to manage the user as is described here.
However, the request.user will be available when receiving requests from a client SDK using an authenticated user.

Resources