Hashing payload data when adding a new user in a Facebook Custom Audiences - facebook

i need an help with the API to add a user in a custom audience.
Looking at the doc it seems not clear if it has to be hashed every single attribute of the payload.data key or not.
On the documentation (https://developers.facebook.com/docs/marketing-api/reference/custom-audience/users/v2.9) it seems like the hash in not required but in this other article (https://developers.facebook.com/docs/marketing-api/audiences-api) seems like each one of them has to be hashed.
Any thoughts?

Yes, you need to hash everything apart from external identifiers, see this part of the doc:
You must hash your data as SHA256; we don't support other hashing
mechanisms. This is required for all data except External Identifiers.
Before hashing, normalize your data. Only First name FN and Last Name
LN support special characters and non-Roman alphabet. For best match
results, provide the Roman alphabet translation with no special
characters.
External identifiers are just extern_id which isn't applicable to most people anyway.
I'd recommend using one our our SDKs if possible as we handle all of the hashing for you. For example:
use FacebookAds\Object\CustomAudienceMultiKey;
use FacebookAds\Object\Fields\CustomAudienceMultikeySchemaFields;
$users = array(
array('ExternId123', 'FirstName', 'test2#example.com', 'LastName1'),
array('ExternId456', 'FirstNameTest', '', 'LastNameTest'),
array('ExternId789', '', 'test3#example.com', 'LastNameTest'),
);
$schema = array(
CustomAudienceMultikeySchemaFields::EXTERN_ID,
CustomAudienceMultikeySchemaFields::FIRST_NAME,
CustomAudienceMultikeySchemaFields::EMAIL,
CustomAudienceMultikeySchemaFields::LAST_NAME,
);
$audience = new CustomAudienceMultiKey('<CUSTOM_AUDIENCE_ID>');
$audience->addUsers($users, $schema);

Related

ramsey/uuid - validate a name-based hashed has the name that we assign it to the uuid

Any reliable uuid package from Packagist that I can download and use it for Slim framework?
Ideally,I would an uuid that I can hash a type, e.g. php, into the string. then i can check if that uuid has 'php'.
EDIT:
How can I validate a name-based hashed has the name that we assign it to the uuid?
// Generate a version 3 (name-based and hashed with MD5) UUID object
$uuid3 = Uuid::uuid3(Uuid::NAMESPACE_DNS, 'php.net');
$uuid = $uuid3->toString();
For instance:
if ($uuid3->getName($uuid) === 'php.net') {
// do something
}
Is this possible?
The best UUID package is https://github.com/ramsey/uuid
Just use composer require ramsey/uuid to install it.
Ideally,I would an uuid that I can hash a type, e.g. php, into the string. then i can check if that uuid has 'php'.
I don't understand this. UUIDs create a unique string. From Wikipedia:
A universally unique identifier (UUID) is a 128-bit number used to identify information in computer systems. The term globally unique identifier (GUID) is also used.
When generated according to the standard methods, UUIDs are for practical purposes unique, without depending for their uniqueness on a central registration authority or coordination between the parties generating them
Edit.
To answer your new question…
You can't reverse a hash, so you need to hash again and compare.
$uuid = Uuid::uuid3(Uuid::NAMESPACE_DNS, 'php.net')->toString();
$domainFromUser = 'example.com';
$userUuid = Uuid::uuid3(Uuid::NAMESPACE_DNS, $domainFromUser)->toString();
if ($uuid === $userUuid) {
// user provided the right domain
}

Perl Dancer2 Authentication Password Management

So any one who has used perl dancer knows that to authenticate a user on login you can call authenticate_user
authenticate_user(
params->{username}, params->{password}
);
This is part of the Auth::Extensible plugin.
To me it looks like it encourages the use of storing passwords in plain text! Sure you can hash the password first then make sure the stored password is the same hash but this seems to be more of a work around and i found isn't guaranteed to work. I have only got this to work using sha1 which shouldn't be used. I want to use Bcrypt but the passphrase simply wont match. Possibly odd characters not matching i'm not sure.
The thing is using the dancer Passphrase plugin i can already validate the username and password without even needing to rely on authenticate_user to verify them. But for the dancer framework to consider the user logged in you still have to call authenticate_user which must be passed the password.
I'm completely stuck. I'm curious how other people have managed to use proper password management in dancer2?
Firstly, I'll echo the "you almost certainly don't need to be using authenticate_user()" comments. The plugin can handle all that for you.
However, "it doesn't hash it" is wrong; here's how it works. The
authenticate_user keyword loops through all auth realms configured, and for
each one, asks that provider's authenticate_user() method to see if it accepts
the username and password. The Database provider (and the others) fetch the
record from the DB, and use $self->match_password() (which comes from the
Provider role) to validate it; that code checks if the stored password from
the database starts with {scheme} and if so, uses
Crypt::SaltedHash->validate to validate that the user-supplied password (in
plain text, as it's just come in over the wire) matches the stored, hashed
passsword ($correct in the code below is the stored password):
if ( $correct =~ /^{.+}/ ) {
# Looks like a crypted password starting with the scheme, so try to
# validate it with Crypt::SaltedHash:
return Crypt::SaltedHash->validate( $correct, $given );
}
So, yes, if your stored password in the database is hashed, then it will match
it if the password supplied matches that hash.
For an example of what a stored hashed password should look like, here's
the output of the bundled generate-crypted-password utility:
[davidp#supernova:~]$ generate-crypted-password
Enter plain-text password ?> hunter2
Result: {SSHA}z9llSLkkAXENw8FerEchzRxABeuJ6OPs
See the Crypt::SaltedHash doco for details on which algorhythms are
supported by it, and the format it uses (which "comes from RFC-3112 and
is extended by the use of different digital algorithms").
Do bear in mind that the code behind authenticate_user is exactly what's used
under the hood for you.
For an example of just letting the plugin do the work for you, consider:
get '/secret' => require_login sub {
my $user = logged_in_user();
return "Hi, $user->{username}, let me tell you a secret";
};
... that's it. The require_login means that the plugin will check
if the user is logged in, and if not, redirect them to the login page
to log in. You don't need to call authenticate_user yourself, you
don't need to set any session variables or anything. logged_in_user()
will return a hashref of information about the logged in user (and because
the route code has require_login, there's guaranteed to be one at this
point, so you don't need to check).
If you need to check they have a suitable role, instead of just that they
are logged in, then look at require_role in the documentation instead.
In the documentation for Dancer2::Plugin::Auth::Extensible, the description for authenticate_user() says:
Usually you'll want to let the built-in login handling code deal with authenticating users, but in case you need to do it yourself, this keyword accepts a username and password ...
Which strongly implies to me that you shouldn't be calling this function at all unless you're doing something particularly clever.
I haven't used this module myself, but it seems to me that all the hashing and encryption stuff should be handled by one of the authentication providers and if there's not one that covers the case you use, then you can write one yourself.
Whenever I need to store secure passwords for a Dancer app, I reach for Dancer2::Plugin::Passphrase. I wonder if I should consider writing an Auth::Extensible style authentication provider for it.

REST Resource route naming for get and ResourceByID and ResourceByName

I am trying to write 2 Rest GET methods.
Get user by Id
Get user by userName.
I need to know if there is any resource naming convention for this. Both my id and username are strings.
I came up with:
/api/{v}/users/{userid}
/api/{v}/users/username/{username}
However, 2) doesn't seem correct and if I change 2) to /api/{v}/users/{username}, I am mapping to 1) as both id and username are strings. Or is it considered acceptable to use /api/{v}/userbyName/{username}?
How should I name my resource route in case 2) ?
First of all: https://vimeo.com/17785736 (15 minutes which will solve all your questions)
And what is unique? Is the username unique or only the id or both are unique?
There is a simple rule for all that:
/collection/item
However, 2) doesn't seem correct and if I change 2) to /api/{v}/users/{username}, I am mapping to 1) as both id and username are strings.
If your item can be identified with an id and also with an unique username - it doesn't matter if it's the username or the id - simply look for both (of course your backend needs to handle that) and retrieve it.
According to your needs this would be correct:
/api/{v}/users/{userid}
/api/{v}/users/{username}
but I would choose only to use: /api/{v}/users/{userid} and filter by username only with a query parameter (description for that down there below)
Also will I break any rules if I come up with
/api/{v}/userbyName/{username}
Yes - /api/{v}/userbyName/{username} will break the rule about /collection/item because userByName is clearly not a collection it would be a function - but with a real restful thinking api there is no function in the path.
Another way to get the user by name would be using a filter/query paramter - so the ID will be available for the PathParameter and the username only as filter. which than would look like this:
/api/{v}/users/?username={username}
This also don't break any rules - because the query parameter simply filters the whole collection and retrieves only the one where username = username.
How should I name my resource route in case 2) ?
Your 2) will break a rule - so I can't/won't suggest you a way to do it like this.
Have a look at this: https://vimeo.com/17785736 this simple presentation will help you a lot about understanding rest.
Why would you go this way?
Ever had a look at a javascript framework like - let's say ember. (Ember Rest-Adapter). If you follow the idea described up there and maybe also have a look at the json format used by ember and their rest adapter - you can make your frontend developer speed up their process and save a lot of money + time.
By REST you send back links, which can contain URI templates. For example: /api/{v}/users/{userid} in your case, where v and userid are template variables. Since the URI structure does not matter from a client perspective you can use whatever structure you want. Ofc. it is more convenient to use nice and short URIs, because it is easier to write the routing with them.
According to the URI standard the path contains the hierarchical while the query contains the non-hierarchical part of the URI, but this is just a loose constraint, in practice ppl use both one.
/api/{v}/users/name/{username}
/api/{v}/users/name:{username}
/api/{v}/users?name="{username}"
Ofc. you can use a custom convention, for example I use the following:
I don't use plural resource name by collections
I end collection path with slash
I use slash by reducing a collection to sub-collections or individual items
I don't use slash to give the value of a variable in the path, I use colon instead
I use as few variables and as short URI as I can
I use query by reducing a collection to sub-collections especially by defining complex filters with logical operators
So in you case my solution would be
/api/{v}/user/
/api/{v}/user/name:{username}
/api/{v}/user/{userid}
and
/api/{v}/user/?firstName="John"
/api/{v}/user/?firstName="John|Susan"&birthYear="1980-2005"
or
/api/{v}/user/firstName:John/
/api/{v}/user/firstName:John|Susan/birthYear:1980-2005/
etc...
But that's just my own set of constraints.
Each resource should have a unique URI.
GET /users/7
{
"id": 7,
"username": "jsmith",
"country": "USA"
}
Finding the user(s) that satisfy a certain predicate should be done with query parameters.
GET /users?username=jsmith
[
"/users/7"
]

Perl Net::LDAP - Fetch DN without Search?

I have the DN of the LDAP entry. I know I could search for it: Doing something like this:
my $search = $ldap->search(
base => $dn,
scope => "base",
filter => "(objectclass=*)",
);
But, I don't need to do a search. I have the DN. I simply want to pull up the DN entry and do my operations directly on that. Something like this:
my $dn_entry = $ldap->get( $dn );
Is there a method to get the DN entry from the DN string itself, or do you have to search for the entry even if you know the DN itself?
Using LDAP, clients must always search or use an extended operation to get data. If you're interested in all the attributes associated with an entry, and the DN is known, use the following parameters in a search request:
baseObject: the DN that is known
search scope: base
filter: either (&) or (objectClass=*)
the list of attributes to be returned. Some APIs use * for all user attributes and + for all operational attributes.
What it sounds like you are saying is that you have stored the "Distinguished Name" (a string) rather than the DN entry (a Net::LDAP::Entry object). If this is the case, I believe you have to create a new Net::LDAP::Entry object from the DN. The documentation indicates that you can apply operations directly to such an object without synchronizing with the server, but this won't supply all the data for the given DN. If you need the server's data, you need to get it via $ldap->search(...).
Have you considered using the Net::LDAP::LDIF mechanism for storing DN data locally?

How can I generate a unique ID using a hash in Perl?

I am writing a message transfer program between multiple clients and server.
I want to generate a unique message ID for every message. It should be generated by the server and returned to the client.
For message transfer, I am using a hash data structure, for example:
{
api => POST,
username => sganesh,
pass => "pass",
message => "hai",
time => "current_time",
}
I want to generate a unique ID using this hash.
I have tried several approaches, MD5 and freeze but these give unreadable IDs. I want some meaningful or readable unique IDs.
I have thought we can use microseconds to differentiate between the IDs but here the problem is multiple clients.
In any situation the IDs should be unique.
Can anyone help me out of this problem?
Thanks in advance.
I suspect you don't want to do what you are asking, but you can do it.
Take the hash key/values and flatten them to an array #foo = (%foo).
MD5 the array to get an ID code - use md5_base64(#foo) if you want it to be 7bit (human readable).
Remember that hashes are not ordered, so you need sort #foo the array if you want it to be repeatable.
In code, something like:
use Digest::MD5 qw(md5_base64);
my $foo = {
api => POST,
username => sganesh,
pass => "pass",
message => "hai",
time => "current_time",
};
my $id = md5_base64(sort %$foo); # in my case eRR9QzGN1n+nIl1TDmclEA
To be honest, I think you are better off generating a unique random ID (a token) and giving it to the client to return to you, but then from your question, I don't know your motivation.
This sounds like a job for Data::UUID.
Furthermore, the unique ID is for a computer. You can abstract that anyway that you like for the humans. :)