I'm using the example code from the SurrealDB Features page for a user/pass system
DEFINE SCOPE admin SESSION 1d
SIGNUP ( CREATE user SET user = $user, pass = crypto::argon2::generate($pass) )
SIGNIN ( SELECT * FROM user WHERE user = $user AND crypto::argon2::compare(pass, $pass));
Unfortunately, the docs don't say how to log into the scope. Can I do this with SurrealQL or an API endpoint?
High level answer: you call signin from whichever client library you are using, at the moment most of this is still in development, e.g. see https://github.com/surrealdb/surrealdb.js
Low level answer, there are multiple types of logins, the regular root login requires user and pass. For a scope login, you specify NS, DB, and SC values, for namespace, database and scope respectively, then you add any values needed for the scope.
You can connect to a websocket at ws://<host>:<port>/rpc, then send commands as json in the format
{
"id": <an id so you can identify responses later on>,
"method": <one of the available commands>,
"params": <an array of parameters>
}
As a minimal example, lets create some commands to signin to the scope you defined:
method params
------ ------
signin {
"NS": <ns>,
"DB": <DB>,
"SC": "admin",
// these parameters can be anything you request in the scope
"user": <user>,
"pass": <pass>
}
use <namespace>, <database>
// use your session ...
Related
I need some help. I need to create a case in a Account with all the details basically, all the fields, using REST API but it I am not able to figure out, how to insert a record for creating a case.
Could you please guide me, how to create a case using REST API in Salesforce?
Do you use a library such as https://pypi.org/project/simple-salesforce/0.3/ or do you need to craft the REST messages manually?
You'd need to do it in 2 calls, login first (unless you have session id already) and then
POST to
https://yourinstance.my.salesforce.com/services/data/v48.0/sobjects/Case
with header
Authorization Bearer <session id goes here, sometimes called "access token" too>
and body
{
"Subject": "Hello world",
"Description": "Lorem ipsum dolor sit amet...",
"Origin":"Web",
"AccountId" :"0010g00001mbqU4"
}
should work like a charm (pass an account id value right for your org and you might have more fields to fill in).
So now "only" how to log in. That's a bigger topic and depends if it's a backend thing or you'll have a human interacting with it, maybe logging in to SF and then coming back to your org. There's bit of reading on that (simpler if you'd use SOAP API to log in)
For example this would work if I didn't redact all sensitive stuff
POST to
https://login.salesforce.com/services/oauth2/token
with header
Content-Type application/x-www-form-urlencoded
and body
grant_type=password
&client_id=(ask your admin for "connected app")
&client_secret=(ask your admin for "connected app")
&username=redacted%40example.com
&password=redacted
Should return
{
"access_token": "<session id here, use it as Authorization header in next calls>",
"instance_url": "<use this as base url of all next calls>",
"id": "<call GET to this (with the Auth header) to learn more about user",
"token_type": "Bearer",
"issued_at": "1593684589157",
"signature": "redacted"
}
Again - don't do it all by hand if you can, use one of Python libraries for Salesforce.
from simple_salesforce import Salesforce
sf = Salesforce(
username='user name of salesforce account',
password='password',
security_token='token')
Sample data
data ={
"Name" : "ABCD",
"Contact" : "123456789",
"Description":"Radio has damaged because of handling."
}
create record
x = sf.Account.create(data)
I would like to make an application in React Native that allows to work in two modes, parent and child. The initial stage is registration with Firebase, then after adding additional information about the role (parent / child), registering both the child and parent, and after logging in both of them, the child will share location and parent will receive it.
I would like to add additional fields such as role (parent / child) in my application in React Native + Firebase, to later create other functionalities of the application based on the role.
Registration:
firebase
.auth()
.createUserWithEmailAndPassword(email, password)
.then(userCredentials => {
return userCredentials
.user.updateProfile({
displayName: name,
})
.additionalUserInfo.profile = {
role: role,
}
})
Homescreen
const { displayName } = firebase.auth().currentUser;
const { role } = firebase.additionalUserInfo.profile;
this.setState({displayName, role});
and role returns undefined.
The properties that you can store on a user profile are defined by Firebase Authentication. You can't just add additional properties to it as you see fit. At best Firebase will simply ignore those, but likely it will also explicitly reject them (throwing an error).
If you want to store additional information about a user, you have two main options:
Store the additional information as custom claims in the user's authentication token.
Store the additional information in an external database, such as the Firestore and Realtime Database that are part of Firebase.
While storing the data as custom claims is pretty close to what you want to accomplish, you'll need to keep a few things in mind:
Custom claims are used for authorization purposes, and for that reason can only be set from a trusted environment (such as your development machine, a server you control, or Cloud Functions). So you can't simply set the role from within the app, and will need a separate process to add that claim.
After setting a custom claim on a user profile it may take up to an hour before that change is visible in the client. If you need it sooner, you can force the user to sign in again, or refresh their ID token.
Custom claims are sent with every request you make to Firebase resources, and for that reason are very limited in size. There's a maximum size of 1000 bytes for custom claims for a user. While your current role will easily fit into that, it may limit what you can add later.
If instead you store user data in an external database, you'll typically combine it with other information about that user into a users node/collection. In here you'd store a document/node for each user based on that user's UID, and then their profile information.
So something like:
users: {
uidOfAleksandra: {
username: "Aleksandra",
displayName: "Aleksandra Lastname",
role: "parent",
registrationDate: "2020-02-01"
},
uidOfPuf: {
username: "puf",
displayName: "Frank van Puffelen",
role: "child",
registrationDate: "2015-03-07"
},
}
Having this list of user profiles does not only allow you to store the additional information for each user, but would also allow you to query that list of users from within your app, something that the Authentication API doesn't allow from within application code.
I'm trying to authenticate with spotipy using Authorization Code Flow like this:
token = util.prompt_for_user_token(username, scope, client_id=client_id,
client_secret=client_secret,redirect_uri=redirect_url)
When I assign any string to "username", I'm asked to authenticate the request in a browser which is popping up; everything works fine.
When I set a different string to "username" before running my code a second time, the authentication is done against the previously authenticated username (which is still authenticated in the browser session); just as if the value of "username" is not taken into account at all.
Also, I seem to be able to set any arbitrary value to "username" like "pipapo"; when I login to my Spotify account (which isn't "pipapo", obviously) this one is authenticated and methods like current_user_saved_tracks() do get the resources of the account authenticated instead of "pipapo".
Anyways: The access_token and refresh_token are saved to the cachefile .cache-pipapo; thus saving the credentials of the "who-ever-logged-into-the-browser" to the file named after the "wrong" account.
So: What is this parameter good for then, if ultimately the user's interactive selections are responsible for what the code is doing? And why is this even a required parameter if more or less not utilized in the auth process?
I just had a look at spotipy/util.py myself, how def prompt_for_user_token(...) is designed and what parameter "username" is used for; indeed, it is used for defining the caching file name only to hand it over to oauth2.SpotifyOAuth() like so:
cache_path=".cache-" + username
So, you can use any value here; it does not need to be the correct username, necessarily.
I think I'm close, but there's just something I'm missing:
GIVEN:
We just want to be able to open our app, get the UserID from salesforce (which would match the UserID in our app), and log us in ... seems easy enough.
We are trying to use the open source C# component AspNetSaml https://github.com/jitbit/AspNetSaml
I have a cloud instance that hosts our app, for testing:
The URL to get to our app would be something along the lines of: http://1.2.3.4/OurCompanyApp/app.wgx
SALESFORCE:
I didn't initiate this process, but I do see that in Salesforce we have it setup as an Identity Provider. So I see this information under Identity Provider:
Issuer: https://our-company-stuff.my.salesforce.com
Label: SelfSignedCert_04Nov2016_195856
Unique Name: SelfSignedCert_04Nov2017_195856
Key Size: 2048
Salesforce Identity: https://our-company-stuff.my.salesforce.com/.well-known/samlidp.xml
I did set up a Service Provider via Connected Apps:
Connected App Name: AppTest
API Name: AppTest
Description: AppTest
Start URL: http://1.2.3.4/OurCompanyApp/app.wgx
Enable SAML: true
Entity ID: http://1.2.3.4/OurCompanyApp/app.wgx
ACS URL: http://1.2.3.4/OurCompanyApp/samlconsume.wgx
Enable Single Logout: false
Subject Type: User ID
Name ID Format: urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified
IdP Certificate: Default IdP Certificate
ACTUAL CODE:
//var samlEndpoint = "https://csi1-dev-ed.my.salesforce.com/";
//var samlEndpoint = "https://csi1-dev-ed.my.salesforce.com/.well-known/samlidp.xml";
(one of these would be un-commented)
var request = new AuthRequest(
"http://1.2.3.4/OurCompanyApp/app.wgx", //put your app's "unique ID" here
"http://1.2.3.4/OurCompanyApp/samlconsume.wgx" //assertion Consumer Url - the URL where provider will redirect authenticated users BACK
);
string url = request.GetRedirectUrl(samlEndpoint);
Response.Redirect(url);
GetRedirectUrl encrypts this bit of xml:
xw.WriteStartElement("samlp", "AuthnRequest", "urn:oasis:names:tc:SAML:2.0:protocol");
xw.WriteAttributeString("ID", _id);
xw.WriteAttributeString("Version", "2.0");
xw.WriteAttributeString("IssueInstant", _issue_instant);
xw.WriteAttributeString("ProtocolBinding", "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST");
xw.WriteAttributeString("AssertionConsumerServiceURL", _assertionConsumerServiceUrl);
xw.WriteStartElement("saml", "Issuer", "urn:oasis:names:tc:SAML:2.0:assertion");
xw.WriteString(_issuer);
xw.WriteEndElement();
xw.WriteStartElement("samlp", "NameIDPolicy", "urn:oasis:names:tc:SAML:2.0:protocol");
xw.WriteAttributeString("Format", "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified");
xw.WriteAttributeString("AllowCreate", "true");
xw.WriteEndElement();
The URL Returned, that I redirect to, would be something along the lines of (depending upon which endpoint I tried, I tested with both):
https://our-company-stuff.my.salesforce.com/?SAMLRequest=jZJdT8IwGIX%2fStP77oMx2Bq2BCHGJagLTC%2b8Md1WpEnXzn5M%2ffeWgQleSLxr3pxznvO%2b6UKTjvd4ac1BbOm7pdqAYp3B11kwn8SzZI%2bSuG3RdEZSVLfzGjVJTAL3COuogeCZKs2kyODECyAotLa0ENoQYdwoCBMURCgIqzDF0wiH0QsEpZJGNpLfMNEy8ZZBqwSWRDONBemoxqbBu%2bX9BrtEXJ9EGt9VVYnKx10FwVJrqoyDrqTQtqNqR9XAGvq03WTwYEyPfT%2beemnghXHohak%2fMGUs4bJ2voEqv5TaeEfEOcAbZMch%2bOy40Hg8x%2fVS%2fXkDmC%2bOajxurS781%2b3kpz%2fM%2f9N2kGO%2fhX%2fBOoF7%2fODCi3UpOWu%2bwK1UHTF%2fs136OGEt2o9SbIXuacP2jLburJzLj5WixNAMGmUpBH5%2bov7%2bHvk3
RESULTS:
I've tweaked Identity ID's, endpoint's, configurations, but Salesforce never hits our samlconsume.wgx, and all the redirect does is take me to my homepage at: https://our-company-app.salesforce.com/home/home.jsp
I'm at a loss right now. Any help would be much appreciated.
I've been going through the rules guide but haven't found an answer to this.
App users are able to submit "scores" of different types, which are then processed in JS and written to a "ranking" node. I have it set up so that every time a new score is submitted, the rankings are automatically recalculated and a new child is written if the user doesn't exist or updated if the user exists.
My question is how to secure this "ranking" node. Everyone should be able to read it, nobody except the system should be able to write it. This would prevent people from submitting their own rankings and aggregate scores.
EDIT
This is the operation:
Ref.child('rankings').child(uid).once('value', function (snapshot) {
if (snapshot.exists()) {
snapshot.ref().update(user); //user object created upstream
} else {
var payload = {};
payload[uid] = user;
snapshot.ref().parent().update(payload);
}
});
How would I add custom authentication to this call? Also, since I'm using AngularJS, is there any way to hide this custom token or would I have to route it through a backend server?
The key part of your problem definition is:
only the system should be able to write it.
This requires that you are able to recognize "the system" in your security rules. Since Firebase security is user-based, you'll have to make your "system" into a user. You can do this by either recording the uid from a regular user account or by minting a custom token for your "system".
Once you have that, the security for your ranking node becomes:
".read": true,
".write": "auth.uid == 'thesystem'"
In the above I assume you mint a custom token and specify thesystem as the uid.