Cloudant User Logins/Management - authentication

I am fairly new to Cloudant/PouchDB. I have managed to get the PouchDB/cloudant instances to sync properly, so I am able to create databases, PUT data, and read data from both the local and Remote databases.
My issue is with authentication.
I'm not sure how to handle the authentication in my scenario. It seems like i have to create the API key/Password for basic authentication and pass that with each request. But how does my 'User' have access to that information?
In my tests the value is simply hardcoded in my javascript page - which is obviously not ideal. What id like to do is simply have a database of users with hashed credentials, and have the user submit their login username/pass against that database to allow login.
I've done some reading regarding enabling the '_users' database...but i cant seem to find anything that really lays out how that would work fully...
[EDIT]
I've manage to setup the _users database with cloudant, and add a user, and give them a membership to one of my databases.
However, this user still doesnt seem to be able to access the db.
Here is the user:
{
"_id": "org.couchdb.user:jan",
"_rev": "1-ec0b2b9c25815ab71a04df745151a85b",
"name": "jan",
"roles": [],
"type": "user",
"password_scheme": "simple",
"salt": "a4f47458b436e705378224896a3260f2",
"password_sha": "6ba718935b8ee170879973baae1b7ce953fd4258"
}
and here is the response from cloudant regardign the _securty of the db i want 'jan' to access:
My understanding is that i should be able to get a response via
jan:apple#cloudanturl/dbname
Instead i get:
{"error":"forbidden","reason":"_reader access is required for this request"}

Related

how to handle/manage a lot of permissions in access-token? what's the best approach?

I'm getting a "Request header is too long" error when i was trying to access my API and send token in header. How we can manage a permissions in access-token because i have a lot of permissions in access-token it's approximately 15kb in size.
I know it's not recommended to store permissions in access-token then what's the best approach to authenticate and authorize the users on API side?
We are getting all the permissions in access token but now permissions are getting large as we have lot of modules. What is the other way to access user permissions in asp.net core API instead of keeping it in access token?
{
"roles": [
"Admin"
],
"iss": "Issuer",
"sub": "sub",
"aud": [
"https://example.com/api",
"https://example.com/userinfo"
],
"iat": 1666198659,
"exp": 1666205859,
"azp": "azp",
"scope": "openid profile email offline_access",
"org_id": "company1",
"permissions": [
"permission.1",
"permission.2",
........
"permission.150",
]
}
This could be a solution: https://fga.dev/. There's also the open source version: https://openfga.dev/
Basically, since every user has a lot of permissions, you don't store them in the token anymore; you can call this service which stores them for you.
Disclaimer: I am part of the team building this solution :)
You have two options.
You can try to shorten the permissions down using something like the approach here. There are lots of other similar questions with similar approaches. However, know that you limit your number of permissions based on what you inherit from so this may or may not work. You can stick a string into the JWT with each char working as a flag for a permission. This comes with more downsides, namely keeping the data up-to-date.
You setup a remote system for authorization. Something like Policy Server from Duende. This means no authorization data in the JWT. For instance you can make a simple http call to your identity server from your api/client and have the identity server evaluate if the user can do what they want to.
The latter seems right for your scenario because of your large amounts of permissions. It comes with overhead but there isn't really an alternative. https://github.com/Perustaja/PermissionServerDemo is an example that uses the built in ASP.NET Core authorization evaluation along with gRPC for the network calls. You can make something leaner and simpler that basically does the same thing if you don't want a lot of infrastructure.

Buildfire: How can I get subscriber status from user information via the API in an efficient way?

I am using the BuildFire user database.
Using the Public API from an external service, I need to validate that the user is logged in and that they are a subscriber. I have the currentUser's access token.
This works to validate the token:
https://public.buildfire.com/1.0/auth/verify_credentials?access_token={TOKEN}
If the token is valid, the request returns a partial user object:
{
"user_id": "62d59708df0fd803aa64251b",
"created_on": "2022-07-18T17:23:20.793Z",
"is_active": true,
"failed_attempt_count": 0,
"last_access": "2022-07-19T17:08:48.270Z",
"display_name": "",
"last_name": "",
"username": "bill#microsoft.com",
"first_name": "",
"email": "bill#microsoft.com",
"last_updated": "2022-07-19T17:10:27.143Z"
}
Validate user is logged in: DONE
QUESTION:
What is the recommended way to determine if this user is a subscriber?
I think this is a little bit different than the traditional use. Generally, the app will use SSO to use your backend system User Authorization/Authentication. Your system returns back an Access Token to BuildFire. Than when you webview some content in from your server, BuildFire passes you along the AccessToken for you to re-authenticate. If this is a viable option than this is your best option.
However, if the option above isnt viable then you can use BuildFire Gateway to call from your server over to BuildFire's auth servers. You'll need an API Key that may or may not be part of your plan. Here is the documentation you need https://sdk.buildfire.com/AWSGatewayPublicAPI/

Http delete request to Google Directory API returning 412 Precondition is not met: location If-Match

I have been using Postman to send http requests to Google's Directory API. The GET request works fine (which shows that the admin token as well works fine) to get info for a user.
But, what I need to do is delete the user, and when I try this, I get the following back:
{
"error": {
"code": 412,
"message": "Precondition is not met.",
"errors": [
{
"message": "Precondition is not met.",
"domain": "global",
"reason": "conditionNotMet",
"location": "If-Match",
"locationType": "header"
}
]
}
}
I was presupposing that I was missing the etag, which is what I added from the user, but it did not work. I also tried adding "*" to the If-Match tag, and that did not work either. Maybe there is a way with a put or patch request?
The API reference is this: https://developers.google.com/admin-sdk/directory/reference/rest/v1/users/delete
The API does not work on Google's reference page either. I have also tried this in multiple domains where I am the super-admin so the error is not related to a specific super-user or domain.
I have also made sure, in multiple tests, that the user I am trying to delete is not an admin of any type.
I am adding images below to show that the GET api works fine. So I just need to know how to format the API request to be able to delete the user.
Ok, after talking directly to Google and even seeing that Jay Lee (author of GAM) ran into the same problem, we found out that you can't delete a user if:
It has a license of some sort
It's an admin
It has a Google Vault retention rule applied
To be able to delete a user from now on, you must remove all these things (licenses, admin privileges, Vault retention rules) or you must transfer the information of that user to another user (along with whatever else Google asks you to remove beforehand).
The "Precondition is not met" is vague and Google should change this, but it means that one of the three things above have not been removed yet.
Below I am adding multiple links to confirm what I mentioned above as well as the APIs you need to use on users before being able to delete them.
https://groups.google.com/g/google-apps-manager/c/83kR-4MoPk0?pli=1
https://github.com/GAM-team/GAM/releases?gam-releases
https://developers.google.com/admin-sdk/data-transfer/reference/rest/v1/transfers#DataTransfer
https://developers.google.com/vault/guides/holds#python
https://developers.google.com/vault/reference/rest/v1/matters.holds.accounts/list

Insufficient Privileges when trying to display user photos on external sites

I have this situation. Im trying to display user photos from an external site, all the configurations about remote sites are already set. I created a connected app in org A and from org B i'm retrieving the users from org A.
All of this works however i cannot show the photos from those users because for that to happen i have to be able to use the ConnectApi.UserProfiles.GetPhoto method which i'm doing right now but i keep getting the "insufficient privileges" error. I tried getting the AccessToken through postman like this
This redirects me to the login site so i can log into my org with my credentials. After that i get an AccessToken.
Next up, i want to be able to get the photos from users from the external site with the AccessToken, However i'm still getting the same error message "Insufficient Priviledges". Am i missing something? thanks in advance
According to: https://sforcenotes.blogspot.com/2015/10/solution-to-display-salesforce-user.html?showComment=1596211057195#c5848226245946017759
The solution is fairly easy but this does not work
I'm bit lost. You have some app that wants to log in to Salesforce and pull images from it? Or do you want to call out from Salesforce and pull images from external app? For first one you likely need "connected app". But you need "remote site settings" or "named credentials" only for calling out.
I'm assuming it's option 1.
There are lots of ways to log in to SF, SOAP API (just username + password), REST API (lots of OAuth2 options, with username+pass or username + JWT or just OAuth2 client id and user logs in to SF interactively, you don't see the password)... Sounds like you're past this stage?
A successful login response will look bit like that (depends on method used):
{"id":"https://login.salesforce.com/id/00Dx0000000BV7z/005x00000012Q9P",
"issued_at":"1278448832702",
"instance_url":"https://yourInstance.salesforce.com/",
"signature":"0CmxinZir53Yex7nE0TD+zMpvIWYGb/bdJh6XfOH6EQ=",
"access_token":"00Dx0000000BV7z!AR8AQAxo9UfVkh8AlV0Gomt9Czx9LjHnSSpwBMmbRcgKFmxOtvxjTrKW19ye6PE3Ds1eQz3z8jr3W7_VbWmEu4Q8TVGSTHxs",
"token_type":"Bearer"}
You're supposed to take from it the access_token (that's your session id. It'll always start with org's id, compare with Setup -> Company information) and instance_url (that's where you're supposed to send any subsequent requests. No more calling the login gateways: login.salesforce.com, test.salesforce.com or mydomain.my.salesforce.com). If you're getting "Insufficient Privileges" I think you didn't change the endpoint.
You can test you logged in OK by sending a GET to the id endpoint you received. It'll give you OpenId info about your user.
Here's my GET to fetch OpenId data with the "Authorization: Bearer " request
So another GET with same header and I have my ugly mug:
If you want somebody else's picture - query similar to /services/data/v48.0/query?q=SELECT SmallPhotoUrl, FullPhotoUrl FROM User WHERE Id = '005...' should work. Check User fields.
{
"totalSize" : 1,
"done" : true,
"records" : [ {
"attributes" : {
"type" : "User",
"url" : "/services/data/v48.0/sobjects/User/(redacted)"
},
"SmallPhotoUrl" : "https://(redacted)/profilephoto/7293L0000008Tfq/T",
"FullPhotoUrl" : "https://(redacted)/profilephoto/7293L0000008Tfq/F"
} ]
}
The key thing is to use the new endpoint and pass the session id in the header. You might even find it easier to use Chatter API to pull photos (also REST-based)

Can I see a Trello user converting from "ghost" to "normal" via the API?

Our company uses the Trello API to add new users to our organization as part of our onboarding process. We add a user by making a PUT to /1/organizations/orgId/members, which returns a JSON representation of the new user:
{
"id": "521baf66783e22e12f000040",
"confirmed": false,
"fullName": "Bradley Buda",
"memberType": "ghost",
"username": "bradleybuda4",
"email": "bradleybuda#example.com",
}
(some fields anonymized / removed)
We want to store ID of this user in our system for bookkeeping purposes (so we can later remove the account when we terminate Bradley). However, when the "ghost" user actually joins the organization (by clicking the link in the invite email), this user record is replaced by an entirely new one, with a different "id":
{
"id": "521bb6b018c2a109450001d7",
"confirmed": true,
"fullName": "Bradley Buda",
"memberType": "normal",
"username": "bradleybuda4"
}
The email address is not returned in the GET /1/organizations/orgId/members call either, so we can't use that as a primary key. We could use the "username" to track our Trello users, but if the user accepts the invitation using an existing Trello account (rather than creating a new account) then the username will change as well.
Is there any durable way to track invitation acceptance for API-created users? Right now we have to manually keep track of Trello accounts after the invitation is accepted, and we'd like this process to be fully automated. I looked at the GET /1/organizations/orgId/memberships API as well, but those IDs (idMembership) also seem to change when the ghost user goes away. And as far as I can tell there aren't any webhooks that fire when the ghost user disappears.
Your analysis is correct, as far as I can tell. There isn't really a way to track members accepting invitations like you want.
If you're willing to poll the memberships on that organization reasonably frequently (depending on how often you add new employees), then you can correlate each ghost disappearing with the member that appeared at the same time.