I'm a bit lost as to what could be wrong here. I have been following this set of instructions to get my Lambdas to connect to RDS using IAM Authentication according to these instructions:
https://cloudonaut.io/passwordless-database-authentication-for-aws-lambda/
Now, I have checked that my RDS Cluster indeed has IAM Authentication enabled - I have created the user and granted all permissions necessary (done this a few times) and I have verified that the "Signer" step here does, indeed, generate a token that's supposedly valid.
Furthermore, the lambdas have the permissions for rds-db:connect and I even added RDS full access for the lambda role (altho I reckon this shouldn't be necessary).
Still, when I attempt to connect, I simply get this:
"errorType": "Error",
"errorMessage": "Access denied for user 'mydbuser'#'19.196.193.217' (using password: YES)",
"code": "ER_ACCESS_DENIED_ERROR",
"errno": 1045,
"sqlState": "28000",
"sqlMessage": "Access denied for user 'mydbuser'#'19.196.193.217' (using password: YES)",
I also noticed that the token I get back has some URL encoded bits so I tried URL decoding it, but that didn't lead anywhere.
I'm out of ideas as to where this could even be failing and the error messages are utterly unhelpful. The grants on the user in question are:
GRANT USAGE ON *.* TO 'mydbuser'#'%'
GRANT ALL PRIVILEGES ON `mydbuser`.* TO 'mydbuser'#'%'
So this hints at it not accepting the token as password. My connection code looks like this:
const mysql = require('mysql2');
...
signer.getAuthToken({
region: 'my+region',
hostname: process.env.ENDPOINT,
port: 3306,
username: 'mydbuser'
}, function(err, token) {
var connection = mysql.createConnection({
host: process.env.ENDPOINT,
port: 3306,
user: 'mydbuser',
password: token,
database: 'mydb',
ssl: { ca: fs.readFileSync(__dirname + '/rds-combined-ca-bundle.pem') },
authSwitchHandler: function (data, cb) {
if (data.pluginName === 'mysql_clear_password') {
cb(null, Buffer.from(token + '\0'));
}
}
});
connection.connect((res, err) => {
console.log(res, err);
});
connection.query(
`SELECT 1;`, ...
Also the full generated token does include the X-Amz-Security-Token so it hints at it being valid from what I've researched so far.
What else could even fail at this point ?
Related
Good morning,
I've encountered a weird issue with my strapi-project.
I have a standard user model which I query for info on the user's profile page via the /users/me endpoint. This was all working fine last week but as I tried logging in this morning, the authorization appeared to not work anymore. I log my user in via this code:
....
async submitForm() {
axios.post('http://localhost:1337/auth/local', {
'identifier': this.email,
'password': this.password
})
.then((response) => {
const { jwt, user } = response.data;
window.localStorage.setItem('jwt', jwt);
window.localStorage.setItem('userData', JSON.stringify(user));
router.push('/dashboard');
})
.catch((e) => {
this.$store.commit('LOGIN_ERROR', e)
});
},
...
Which then redirects to my dashboard which queries the /users/me endpoint like so:
let token = localStorage.jwt;
axios.get(`http://localhost:1337/users/me`, {
headers: {
Authorization: `Bearer ${token}`
}
})
.then((response) => {
console.log(response.data);
})
A few days ago this was working fine, also the token variable used in the post contais the token returned from the backend after logging in. Now strapi gives me an error in the console:
[2021-10-16T07:16:52.568Z] debug GET /users/me (5 ms) 500
[2021-10-16T07:17:03.231Z] debug POST /auth/local (76 ms) 200
[2021-10-16T07:17:24.915Z] error TypeError: Cannot read property 'type' of null
at module.exports (/home/user/WebstormProjects/strapi-project/node_modules/strapi-plugin-users-permissions/config/policies/permissions.js:35:14)
at async /home/user/WebstormProjects/strapi-project/node_modules/strapi-utils/lib/policy.js:68:5
at async serve (/home/user/WebstormProjects/strapi-project/node_modules/koa-static/index.js:59:5)
at async /home/user/WebstormProjects/strapi-project/node_modules/strapi/lib/middlewares/parser/index.js:48:23
at async /home/user/WebstormProjects/strapi-project/node_modules/strapi/lib/middlewares/xss/index.js:26:9
My first guess was that maybe something with axios was wrong e.g. that the token wasn't sent correctly in the request so I tried the same thing with webstorm's http client:
POST http://localhost:1337/auth/local
Content-Type: application/json
{
"identifier": "test#test.com",
"password": "..."
}
Which returns the user and token:
"jwt": "<TOKEN>",
If I try using this token to authenticate the user, however a get a 401
GET http://localhost:1337/users/me
Authorization: "Bearer <token>"
Accept: application/json
returns
{
"statusCode": 401,
"error": "Unauthorized",
"message": "Invalid token."
}
So I tried figuring out what was going on there and after an hour I noticed that when looking at the user in the backend the user didn't have the authenticated role assigned. When I changed this manually in the backend, the request authorization works again.
So can anyone maybe tell me what is going on here? Because from my understanding, when POSTing valid credentials to /auth/local the user's role should change to Authenticated, which was working some days back.
Is there something I'm missing?
Any help would be greatly appreciated,
greetings, derelektrischemoench
Okay, so let me reply to your first part:
"Because from my understanding, when POSTing valid credentials to /auth/local the user's role should change to Authenticated"
Answer is, not really. When you send valid credentials to the auth/local, Strapi just checks the database for matching username/email and password. If a user is found, then it fetches the role assigned that user and puts all the data in ctx.state.user.role. So you could have many other roles, like Viewer, Commenter etc with each having different set of access limits.
The different roles can be created here:
http://localhost:1337/admin/settings/users-permissions/roles
So depending on the roles assigned, Strapi will just fetch and store the values in ctx.state.user.role on each request via the strapi-plugin-users-permissions plugin for your convenience, so that you can easily check which user it is and which role it has in any controller or service file using the ctx from the request to provide any additional functionality.
You can check how it does it in the following file:
node_modules/strapi-plugin-users-permissions/config/policies/permissions.js
Now coming to what could have caused it:
Well it could have been you yourself. Possibly while saving the user or viewing user details you could have removed the role from the user and saved the record.
The other possibility could be a database switch.
It can also be a Strapi version upgrade that caused, but it's highly unlikely.
You could have a update query in the your code that updates the user model, where you might have missed the role parameter. So check your code once.
Nevertheless, it can simply be solved by re-assigning the user roles via the users module.
Im trying to use the aws-sdk to acces my linode S3 compatible bucket, but everything I try doesn't work. Not sure what the correct endpoint should be? For testing purposes is my bucket set to public read/write.
const s3 = new S3({
endpoint: "https://linodeobjects.com",
region: eu-central-1,
accesKeyId: <accesKey>,
secretAccessKey: <secretKey>,
});
const params = {
Bucket: bucketName,
Key: "someKey",
Expires: 60,
};
const uploadURL = await s3.getSignedUrlPromise("putObject", params);
The error im getting
code: 'CredentialsError',
time: 2021-07-15T08:29:50.000Z,
retryable: true,
originalError: {
message: 'Could not load credentials from any providers',
code: 'CredentialsError',
time: 2021-07-15T08:29:50.000Z,
retryable: true,
originalError: {
message: 'EC2 Metadata roleName request returned error',
code: 'TimeoutError',
time: 2021-07-15T08:29:49.999Z,
retryable: true,
originalError: [Object]
}
}
}
It seems like a problem with the credentials of the environment that this code is executed in and not with the bucket permissions themselves.
The pre-signing of the URL is an operation that is done entirely locally. It uses local credentials (i.e., access key ID and secret access key) to create a sigv4 signature for the URL. This also means that whether or not the credentials used for signing the URL are valid is only checked at the moment the URL is used, and not at the moment of signing the URL itself.
The error simply indicates that from all the ways the SDK is trying to find credentials (more info here) it cannot find credentials it can use to sign the URL.
This might be unrelated, but according to the documentation, the endpoint should be the following: The endpoint URI to send requests to. The default endpoint is built from the configured region. The endpoint should be a string like 'https://{service}.{region}.amazonaws.com' or an Endpoint object. Which, in the code example above, is not the case.
You should set the endpoint to be eu-central-1.linodeobjects.com. When using Linode object storage the region is not determined by the endpoint that you use.
I am trying to create login authentication with ldap js. I set up all Credentials and everything is working fine, but the problem is I can bind a user just with his Uid (user id aka username), it didn't ask for a password and I don't know how to fix this it must ask for Uid and userPAssword to connect
I tried to connect to with the same credentials including userPassword but it didn't work for me
ldapConfig.js
in this file i set up all ldap config
'url': 'ldap://*************',
'port': '***',
'timeout': '',
'connectTimeout': '',
'secret': '**********',
'reconnect': true,
'filtre': '(&(ObjectClass=*******)',
'search_dn': 'ou=******,dc=****,dc=****',
'domain': 'cn=******,dc=****,dc=****'
login.js
in this file i tried to connect to ldap server and it work realy fine and then i want to get user by uid
const server = ldapConfig.url
const ldapDomain = ldapConfig.domain
const password = ldapConfig.secret
const searchDomain = ldapConfig.search_dn
const client = ldap.createClient({
url: server
})
client.bind(ldapDomain, password, err => {
assert.ifError(err)
})
const opts = {
scope: 'sub',
filter: ldapConfig.filtre + `(mail=${request.body.mail}))`
}
client.search(searchDomain, opts, (err, res) => {
assert.ifError(err)
res.on('searchEntry', entry => {
console.log(entry.object)
} )
I hope it's clear . Thanks
Unauthenticated bind (a seemingly successful bind when you supply a userID and null password) may be enabled in your directory. If you are using OpenLDAP, as the quesstion tags indicate, check slapd.conf for allow bind_anon_cred.
Unless there is a specific need for unauthenticated bind, I disable it on the directory servers. In the rare cases where unauthenticated bind is required, all applications authenticating against the directory need to validate user input before attempting to bind -- that is, verify that the input username and password values are not null.
I’m afraid I don’t understand how this is supposed to work at all. How does slingshot know the address to find my s3 bucket? Is this completely determined by the access keys?
This is the code I have in my server/files.js:
var imageDetails = new Mongo.Collection('images');
Slingshot.fileRestrictions("myImageUploads", {
allowedFileTypes: ["image/png", "image/jpeg", "image/gif"],
maxSize: 2 * 1024 * 1024,
});
Slingshot.createDirective("myImageUploads", Slingshot.S3Storage, {
AWSAccessKeyId: "AWSAccessKeyId",
AWSSecretAccessKey: "AWSSecretAccessKey",
bucket: "mybucketname",
acl: "public-read",
region: "us-west-1",
authorize: function () {
if (!this.userId) {
var message = "Please login before posting images";
throw new Meteor.Error("Login Required", message);
}
return true;
},
key: function (file) {
var currentUserId = Meteor.user().emails[0].address;
return currentUserId + "/" + file.name;
}
});
And this is my settings.json file
{
"AWSAccessKeyId" : "my access key",
"AWSSecretAccessKey" : "my secret access key",
"AWSBucket" : "mybucketname"
}
I get this error in my browser:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://mybucketname.s3-us-west-1.amazonaws.com/. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).
But I have a CORS configuration in my theportdata bucket.
The first step, I guess, is there any way to check if my application is making contact at all with my s3 bucket? Like I said, I don’t really understand how slingshot finds the bucket.
SOLVED
Changed "region: us-west-1" to "region: us-west-2" and it works.
There is also no need for the AWSAccessKeyId and AWSSecretAccessKey, since slingshot finds this automatically from settings.json.
Apparently all that's needed for an address is the bucket name and the region.
https://docs.aws.amazon.com/AmazonS3/latest/dev/WebsiteHosting.html
This is my router:
expressJwt = require('express-jwt')
router.post '/signin' , controller.signUp
router.get '/signout/:id' , expressJwt(secret:secretToken, isRevoked: isRevokedCallback), controller.signOut
This is my signOut endpoint:
exports.signOut = (req, res) ->
console.log res.user
What do I need to put into my endpoint to revoke the token.
I tried putting this function into my router:
isRevokedCallback = (req, payload, done) ->
for key, value of payload
console.log(key + ' ' + value)
# The below part does not work. Also I don't know what data should refer to
issuer = payload.iss
tokenId = payload.jti
data.getRevokedToken issuer, tokenId, (err, token) ->
if err
return done(err)
done null, ! !token
return
The list comprehension indeed logs out:
iat 1436437563
exp 1436653563
And there is also also a user object in my endpoint logged out:
user [object Object]
Now how to put the pieces together and revoke the JWT Token, so that the user who's token it is is not able to login anymore with that Token (or alternatively expire it immeadiately)?
Here is some sample console log of my user object:
{ user:
{ __v: 0,
_id: '559e6aad50cdf686db31ea55',
local:
{ password: '$2a$08$YBvzOWADlw9tZCDh3aG/j.gV.Tbaesk3pLbbiHL/lkGaC08bSbGmy',
email: 'dieter#mustermann.de' } },
iat: 1436445357,
exp: 1436661357 }
GET /user/signout/559e6aad50cdf686db31ea55 401 2.530 ms - 12
ERROR:Error: expected 200 "OK", got 401 "Unauthorized"
1) should sign out via passport.js
I managed this by returning a token: false key, value pair. Another idea would be to send back a token with expirationInSeconds: 1. The old token will still be valid, and this can't be called very secure at all. So set the default token expiration very low or move to another option like blacklists.