Kentico 9 REST service 403 error - kentico

I have a custom page type (kff.SeasonCTA), that I'm trying to access. The goal is the present the data from the custom pages on a static HTML page using jQuery. I've confirmed the REST service is working as i can get the county json object as per the documentation.
I've set authentication to Basic, and the service enabled as Both. I generated a hash with this URL: http://dev.knowledgefirstfinancial.ca/rest/kff.SeasonalCTA?format=json
I get a 403. I read more, and i think it's because i'm doing an ALL. So how can i specify only published pages.
Or is it possible to get all the child data from a cms.folder if i specify the folder by it's GUID?

I'd recommend using basic authentication: create user account and make sure it has all necessary permissions (use impersonation to verify access) and pass that user in authorization header.
It is possible to request all the child by node alias path:
/content/currentsite/<culture>/childrenof/<alias path>
/content/currentsite/en-us/childrenof/news

Related

API returning a USER_LACKS_MEMBERSHIP error

I've built an API-based integration with DocuSign (using their PHP SDK), and am now at the point of deploying to the production server. I have reconfigured everything with the production integration key, public/private key pair, user and account IDs, endpoint URL, etc. replacing the demo ones. The OAuth portion of the conversation is working fine, and I get a valid token back. When I then try to send an envelope, I hit a USER_LACKS_MEMBERSHIP error, and cannot figure out why. As far as I can see, everything about the API user is the same between the demo and production systems.
I've authorized the application and made sure that it's in the list of "Applications with Access to DocuSign".
I have enabled logging, but the only things that are showing up in there appear to be from my own navigation in the site, nothing related to the API calls at all.
Most of the documentation that I can find on this simply repeats the generic error text: "The UserID does not have a valid membership in this Account." If I go to the account admin and look at the list of users, the one I'm expecting is right there, with DS Admin permission; not sure what else might be done to give them "membership". One mentioned not using SendOnBehalfOf, but I'm not, so I can't really remove that.
All the code is identical, just configuration that's changed. Not sure where else to look. Anybody have any suggestions for what to try?
FURTHER INFORMATION
I've tried the getUserInfo call in the SDK, passing the same access token I use for the other call. It returns successfully, showing that it is for the user I'm expecting, in the one group we have, on the production server. And yet, when I enable logging again, as this same user, there is still zero record in the resulting logs of any of this API activity.
Attempts to do things like list templates with the SDK fail with the same USER_LACKS_MEMBERSHIP error.
Using the Diagnostics API (again, through the SDK) to check logging status shows that it is NOT enabled (despite my enabling it in the UI), but can be enabled with a separate call. Subsequently attempting to use listRequestLogs in the SDK generates a 404 error, though the URL matches what's listed in the API documentation (/v2/diagnostics/request_logs). Not sure whether these findings confirm that I'm somehow logging onto the API and the UI with different users (even though the user name and internal ID match), or that there's some problem with the logging facility in DocuSign.
The problem turns out to be the URL I was using for API calls. I switched from demo.docusign.net in testing to www.docusign.net in live, but being in Canada we need to use ca.docusign.net. For those who find this later, you can get the correct base path to use from the oauth/userinfo endpoint, or the getUserInfo() call through the SDK (PHP SDK, at least; don't know what the analogous call would be in others).
There are 3 things to consider:
API calls are made to an endpoint (URL) that contains the account # (either GUID or short form) in the url. Take a note of that number in the url.
Auth Token is a token for a specific user in a specific account.
UserId for the specific call. That is a specific user in the account.
If the user is not in the account, or there's a mismatch between #1 and #2 - you'll get this error. You must work with a single account and have it in all places as well as the user must be a member of this account.
Re:
I have enabled logging, but the only things that are showing up in there appear to be from my own navigation in the site, nothing related to the API calls at all.
Since the request logging is not showing your API activity, the problem is that the person you've logged in as on the web tool is not the same as the person (user id) that you've logged in as on your application.
Solution for OAuth Authorization Code authentication: double check that when your app is logging into DocuSign, you're using the account.docusign.com authentication server, not the account-d.docusign.com auth server. (Look at the URL in your browser during the login sequence.)
Solution for OAuth JWT authentication: re-check that the impersonated user id is from the production system and you're using the right authentication server

Blueprism Code Producing 403 Forbidden Error

I am trying to use Blueprism to download pdf files from Sharepoint.
I am using the below code. Url and Path are both variables which get passed through. This is producing a 403 forbidden error. I believe that Blueprism is required to pass credentials to Sharepoint before it will be allowed to download the file. Is this possible?
Using wc As New System.Net.WebClient()
wc.DownloadFile(Url, Path)
End Using
I don't think you have a password related issue, likely the SharePoint is recognising your account access via AD group or SSO of some kind. 403 means the server has understood your request but is denying to fulfil it because of an access reason on the profile you have. Make sure you can manually download the file on the profile you are emulating for a start then also check the profile the bot is operating under (not necessarily yours in some cases ) has access to said file.
Literally 403 is a request that relates to an access issue so somewhere something doesn't have the correct access lined up
First of all, is this a Sharepoint Online or OnPremises version? As you understand, you are connecting to web resource via an API and as such you have to get authenticated and authorized to access those resources.
If it's SPO, you can use the API component for SharePoint integration from DX and configure.
In case of SP On prem, you have to customize a lot to achieve your results.

Obtaining Instagram Access Token

We have a client who has a simple Instagram feature on the site to pull photos by a certain tag. They just noticed it isn't working. Getting an error - invalid access token. I guess since the 1st because of the updates. We didn't used to need an access token since we're not doing anything with users - just tags.
Now it looks like we need one and the documentation makes zero sense on how to obtain one. And it seems like they're not accepting most apps. The app is in sandbox mode too. So I'm assuming it's because it got switched to that? Got no notification of this happening.
The first step in documentation to get an access token is "Direct the user to our authorization url." What does that even mean? There's not a link provided or anything. It also says "Company Name, Contact Email and Privacy Policy URL are required to start a submission." Our app doesn't have a privacy policy... it's just a simple tag feed. I don't understand why everything is so complex to have a simple tag feed.
Is there a wait time to get the app approved..if it gets approved... Do I have to have it approved before getting an access token? This isn't outlined anywhere.
You got it right. As of June 2016 any Instagram API calls require an access token.
Getting an access token is described in the documentation. App approval is not required.
There are two ways to get one: server-side or client-side. The second option (called implicit authentication) can only be used when implicit OAuth is enabled in the client settings (Manage Clients > Edit Client > Security > Disable implicit OAuth). It is disabled by default.
In either case you need to redirect the user to the authorization URL to obtain an access token.
The URL for explicit mode (server side) is:
https://api.instagram.com/oauth/authorize/?client_id=CLIENT-ID&redirect_uri=REDIRECT-URI&response_type=code
The URL for implicit mode (client side) is:
https://api.instagram.com/oauth/authorize/?client_id=CLIENT-ID&redirect_uri=REDIRECT-URI&response_type=token
After this you will be redirected to the REDIRECT-URI, which will be passed an argument. For explicit mode this will be a query string with a code, while for implicit mode you will get the access token directly as a hash:
http://your-redirect-uri?code=CODE
http://your-redirect-uri#access_token=ACCESS-TOKEN
For implicit mode you can then get the access token from the window.location.hash in Javascript.
For explicit mode, however, you need to further process the code to obtain the access token. You can read how this can be done in the API Documentation. I'm not going to take this any further here.
The problem is that every user who wants to see your feed needs to login to Instagram (and have an account) in order to view it. In your case this might not be desired. However, there are a few options to get around this (rather annoying) problem:
You can reuse your own (already obtained) access token(s) to display the Instagram feed for every user. You will need to be aware of rate limits for each token. For sandboxed apps this is 500 API calls / hour, while live mode allows 5000 API calls / hour. [source] You could store tokens in a table and use them in a round-robin manner, to allow more API calls. This involves manually obtaining a bunch of tokens which your application can use (the more the better). This might not be the ideal solution considering Instagram doesn't warrant access tokens to have an unlimited lifetime.
You can retreive JSON data without authentication by appending /media/ to a user page URL, as described in this post. No tokens or client IDs are required for this to work. However, this only works for users, not for tags. Besides, Instagram doesn't document this feature so it is not garanteed to work in the future.
You can use an aggregator like Juicer or Dialogfeed instead which will handle access tokens for you. This is usually not free of charge.
I'm also in the process of making an Instagram feed for my website, and this is what I concluded from my research. Please bare with any errors I made.
Edit: Here are some more limitations for sandbox apps.
In sandbox mode you can only access data from sandbox users (thus users who received a sandbox invite). This means that:
Media retreived by user, e.g. /users/{user-id}/media/recent, will return an empty response if the user is not any of the sandbox users.
Media retreived by tag, e.g. /tags/{tag-name}/media/recent, will only contain tagged media belonging to sandbox users.
Thus, for a tag feed to work, it needs to be live (reviewed and approved). If you don't want to do this, the only alternative is to use an aggregator as I mentioned above.

SharePoint 2013 Cross-Domain Library Scenario: Authentication Mechanism for Remote App

I have a SharePoint provider-hosted app that exposes a Web API endpoint. I'm using this endpoint as a middle man to call a secured external web service. I want to make calls to my Web API endpoint via javascript in a SharePoint Page (a Publishing Page) in my host web. Since this is a cross-domain call, I'm utilizing SharePoint's cross domain library (SP.RequestExecutor.js). I followed the steps in this article to create my custom proxy page that is required by the cross-domain library. Everything works fine. I can call my service via SP.RequestExecutor with no issues. Now, I just want to require authentication for accessing the Web API endpoint.
The article that I reference states that I'm responsible for the authentication mechanism. I just can't seem to come up with a really secure one and there are literally no examples on the web. I'd really like to leverage the identity of the SharePoint user somehow since only SharePoint users will be hitting the Web API endpoint, I just can't figure out how. SP.RequestExecutor won't let me pass the SPHostUrl querystring parameter when hitting the endpoint, so that's why I can't use the trust relationship between SharePoint and remote app. Does anybody have some ideas for authentication in this scenario that would work well when using SP.RequestExecutor to call my endpoint?
To summarize, you have the following scenario:
You have a SharePoint add in (SharePoint App).
A page on the add in web (app web) needs to call an external service.
You have an external service implemented using ASP.NET Web Api.
The external service needs authentication.
The first issue you need to address is the Same Origin Policy. To overcome this issue, Microsoft documentation describes three options as you know:
The SharePoint Cross Domain Library
The SharePoint Web Proxy
Create a custom proxy page.
However, I think the best bet is to use CORS because it is a W3C recommendation, it's simpler, easier to use, comprehensive, hack-free, and specially: ASP.NET Web API 2 supports CORS.
The other issue to address is authentication. Unfortunatelly Microsoft documentation doesn't provide any example nor hint, it simply tells you it's your responsability. Searching the web doesn't provide any example or hint either. So I conclude: You need to invent an authentication mechanism. Several authentication protocols are based on chalenges such as NTLM authentication. Email address validation uses also a chalenge, it chalenges you to read an email sent to the emails address. I propose you a mechanism based on the same paradigm. I chalenge the user to create a specific list item on the SharePoint App Web (add in). So we need a list on the App Web called AutenticationChalenges with the following fields:
ID: autoincrement built in field.
ChanlengeValue: single line of text.
CreatedBy: user built in field.
The authentication proccess has the following steps:
1.- JavaScript on a App Web page calls https://myexternalservice.mycompay.com/create-chalenge web api endpoint with the following payload:
{
"UserId": "3432" // the SharePoint UserId
"AppWebUrl": "https://mysharpointonline-e849d5bbe0ddc2.sharepoint.com/MySharePointApp"
"HostWebUrl": "https://mysharepointonline.sharepoint.com/MySharePointApp"
}
2.- The external server generates two 16-32 bytes random values: ChalengeValue and CorrelationToken, and it inserts them along with the payload into some storage such a table like the following:
CREATE SEQUENCE authentication_chalenges_authentication_chalenge_id_seq
START WITH 1;
CREATE TABLE authentication_chalenges
(
authentication_chalenge_id int NOT NULL DEFAULT NEXT VALUE FOR authentication_chalenges_authentication_chalenge_id_seq
CONSTRAINT authentication_chalenges_authentication_chalenge_id_seq PRIMARY KEY,
user_id int NOT NULL,
correlation_token binary(16) NOT NULL,
chalenge_value binary(16) NOT NULL,
app_web_url varchar(4000) NOT NULL,
host_web_url varchar(4000) NULL,
created_timestamp datetime NOT NULL
)
Then, the server returns the following result:
{
"ChalengeId": 31232, // the value of authentication_chalenge_id column of the table
"CorrelationToken" : "95AE040FE6844345B36B5E33BE03437F",
"ChalengeValue" : "E38A022B7F744D3BA8C676259AECD607"
}
3.- JavaScript on the App Web page inserts an item into the AuthenticationChanlenges list setting ChalengeValue column = "E38A022B7F744D3BA8C676259AECD607" and calls https://myexternalservice.mycompay.com/login web api endpoint with the following payload:
{
"ChalengeItemId" : 4133, // the ID column of the AuthenticationChalenges SharePoint list
"ChalengeId" : 31232,
"CorrelationToken" : "95AE040FE6844345B36B5E33BE03437F",
"ChalengeValue" : "E38A022B7F744D3BA8C676259AECD607"
}
4.- The external services server look for the row on chalenges table:
SELECT * FROM authentication_chalenges WHERE authentication_chalenge_id = 31232
If the query returns a row and CorrelationToken and ChanlengeValue match, and it has not expired yet, the server connects to sharepoint looking for the item with ID = 4133 on the AuhenticationChalenges list, ands checks that ChalengeValue is equals to E38A022B7F744D3BA8C676259AECD607, and finally it checks that CreatedBy user id is equals to 3432. If all checks success, then it responds with and ok response and sets the authentication cookie. If any of the checks fails then it responds with 401 result.

Accessing Dynamics CRM 2011 data through a website using only HTML5, JS, and CSS

Looking to create a completely external portal using only HTML5, JS, and CSS to show CRM 2011 data. It does not look like I can use REST or SOAP because they cannot authenticate externally. Does anyone know how I would do this?
Thanks!
To do this, your OrganizationData.svc service would need to be externally accessible, and it would need to function without authentication (or, your authentication would need to happen within your javascript - where the end user would be able to read your source code). Either way is not a wise idea, since all of your data would be visible to the world!
If you are only dealing with internal authenticated users, read up on the oDATA endpoint.
If you want to deal with external and/or unauthenticated users, you'll need to find another way to do this that does all of the data filtering & authorization control you need.
I think we normally achieve this using a intermediary integration service. You could have a service which has access to the Org service through conventional CRM authentication, and which provides a number of methods which can be called anonymously (or by custom security) by client code.
For example, a web page calls the 'int' service's 'getContact' method, passing an email address of the user. The 'int' service validates the user's email address and then retrieves the required data from CRM's org service, using credentials stored in a config file (a CRM user with sufficient permissions to serve the 'int' service's methods). The 'int' service then parses the data and returns it to the client code - which has no knowledge of CRM's existence - perhaps as JSON for usability.

Resources