No value being returned by ‘whoami’ Valence API call - desire2learn

A client has been developing a c# MVC program to communicate with the D2L platform using the Valence extensibility libraries. They are able to authenticate their user Id with the platform when registering a new app. However they are facing a problem with the ‘whoami’ API call.
According to the ‘basic’ program in Github, there is a session variable called “valenceUserContext” which get values from the following command after authenticating with the platform.
Session["valenceUserContext"] = vAppcontext.CreateUserContext( Request.Url, vHost );
Unfortunately there were no values returned from the above command (Error is cannot peform binding on a null reference). Do they have to set permissions explicitly for this call in order to get the necessary values returned to the session variable?

There's no mention of user privacy controls for this route in the documentation. There's an API Test Tool that can be used to check the Host, Port, App id, and key. If that works for your client, they should double check these variables in their configuration.

Related

Access to MS Graph blocked by Conditional Access policy

To read information via the Graph API from our Azure environment I used Microsoft.Identity.Client library (version 4.18) to authenticate users. Net framework 4.8 in the background.
This works perfect for some time but now a Conditional Access policy was enabled and the following call ends in an exception.
authResult = Await PublicApp.AcquireTokenByIntegratedWindowsAuth(m_scopes).ExecuteAsync(CancellationToken.None).ConfigureAwait(False)
Exception: AADSTS53001: Device is not in required device state: domain_joined. Conditional Access policy requires a domain joined device, and the device is not domain joined.
dsregcmd /status
+----------------------------------------------------------------------+
| Device State |
+----------------------------------------------------------------------+
AzureAdJoined : YES
EnterpriseJoined : NO
DomainJoined : YES
From my point of view my device is domain joined and there is no reason to block this access.
Same pc as before. Can be tested in parallel. App used with a user without conditional access works. App used with a user who has an conditional access policy assigned fails.
Any idea what I have to change to run my call also with Conditional Access enabled?

AWS web and mobile hub application

On AWS, I wish to create an application that allows a user to sign in via mobile, web or both.
I created a system using API Gateway, Lambdas and DynamoDB for the back end. I have sign in working for web using JavaScript but was having issues finding a Swift example for iOS of the same code (objective C only available). So I created a mobile hub application, imported my existing API and have a working iOS sign in.
The issue is that the iOS side uses the Mobile Hub so I now have 2 different User Pools so you can't sign up on web and log in on mobile (or vice versa).
I tried to change the settings in the iOS app to point to my web app Cognito User Pool settings and remove the secret but it errors as it can not be null or empty.
Why does the mobile hub require a client secret? The JavaScript documentation suggested was bad practice since code can be de-compiled and the secret extracted.
There doesn't seem to be any consistent documentation that explains, what I would guess, as the most common use case of a mobile and web app!
The other issue is that I can download my API client SDK for my API Gateway for use with web app and iOS app. But, the generated mobile hub app includes a REST based call? Am I going crazy here or does the official web approach not link to the official mobile approach?
So the key questions are:
Can or should I change the mobile apps to point at the original
Cognito?
if so should I remove the client secret?
can I effectively ignore the Mobile Hub after set up and use it purely for code generation? Assuming it was then working can I just use the generated client SDK for my API Gateway?
Is there a better way of setting up an iOS (later Android too) and web app?
I've spent considerable time and effort, and tried many approaches.
The "Mobile Hub" nicely sets up the user pool, identity pool, IAM roles etc.
The keys etc are mostly provided in the Info.plist file, although ( unwisely ) the developers of the user pool AWSSignInProvider made it have hardcoded keys in a configuration file.
SO:
If you don't intend to use the "Mobile Hub" console application for making changes to your mobile app configuration, then you won't need any more downloads. In that case, you don't have to worry about changes to Info.plist or the configuration file, and you can edit what you want.
It is unclear if you are going to use the mobile hub created identity pool and just want to insert your user pool, or if you want to change both pools. Obviously if you are using the same identity pool then some of the changes below will not be needed (they will be obvious because you will be changing them to be exactly the same).
So all you have to do is change the ID's to get everything hooked up correctly.
In general you need to fix all the downloaded keys and ID's in Info.plist and the configuration file, and then you need to update the server configuration. In more detail, here are the places you need to change it:
in the app:
update all the keys in Info.plist to be the keys you want. (specifically credentials provider and identity manager keys for google) But if you are using other mobile hub services, check the keys there too.
If you are using s3, and some of the other services the directory names/database names are also stored in the code... I leave it as an activity to find them.
in the file MySampleApp->AmazonAWS->AWSConfiguration.swift edit the keys provided by Mobile hub to match your user pool (do this while quietly swearing under your breath because they are not in Info.plist)
in the console:
put your app name in your user pool APP's list if it is not there, and record the user pool id, app id, and app secret.
click on federated identities and the identity pool created by mobile hub and update the authentication provider to use your cognito user pool id and app id.
if you are changing the identity pool too, then you will need to look at the IAM Roles for your auth and unauth users and specifically edit the policy that is named: .....yourapp....signin_MOBILEHUB_xxxxxxx, and change the identity pool id in that policy to be the one you want to use. Do this for both auth and unauth.
( you can change the id if you only use one pool, or add another to a list of id's like this if you will have multiple identity pools (for test...etc))
"Resource": [
"arn:aws:cognito-identity:*:*:identityPool/us-east-1:8s8df8f8-sd9fosd9f0sdf-999sd99fd",
"arn:aws:cognito-identity:*:*:identityPool/us-east-1:dfsf9099-sd9fosd9f0sdf-sd9f0sdf09f9s"
]
similarly, in the trust relationship associated with the roles, you need to fix the id's, (or handle multiple ID's if you want the role to serve multiple identity pools). Here is how to specify multiple id's there.
"Condition": {
"ForAllValues:StringLike": {
"cognito-identity.amazonaws.com:aud": [
"us-east-1:8s8df8f8-sd9fosd9f0sdf-999sd99fsdfdd",
"us-east-1:dfsf9099-sd9fosd9f0sdf-sd9f0sdf09f9s"
]
},
if you are using google too... you need to make sure that you have an identityProvider in the IAM configuration for google (mobile hub did that for you) and if you are using your own identity pool , in your federated identity pool authorization providers configuration you will need to select google open id provider (and put google in the authorized providers too (but I don't think this part is strictly needed))
facebook doesnt use OpenID Connect, it has a proprietary way of configuring into the authentication providers section, so enter those keys if needed in the identity pool authentication providers section.
And that should be enough to make it work.
And no you are not going crazy... the documentation does not match the current IOS SDK. Mobile hub uses the aws-mobilehub-helper-ios (github) which is built on TOP of the sdk, so the documentation does not apply to that either! Mobile Hub Helper has a nice design, so I recommend you use it, rather than the raw SDK.
(and lastly... and I am out of my depth here because I don't use API gateway, but my understanding was that the API Gateway is a way to get credentials to use AWS Services, and with the mobile hub app you will be using Cognito to get those credentials, so I am not sure you will need to bring the API Gateway into it...at all)
UPDATE
You may want to use no client secret for users of your javascript app, and use a IOS Mobile App on the same pool too. This can be done in two ways:
1) The better way is that you create two different client's in the user pool. For one you will generate a client secret, for the other you will UNCHECK the "generate client secret" box.
Then in your Federated Identity Pool you go to Authentication Providers, and click on Cognito, and specify TWO DIFFERENT PROVIDERS USING THE SAME USER POOL ID. (This is not really two different providers, but that is how the console makes you specify it). And you put the two different client ids in those providers.
Now both the IOS app and the Javascript app can access the pool and get authentication and credentials from the identityProvider and credentialsProvider.
2) A not so good way. The reason this way is worse is because I don't know the impact (if any) it has on the security of your mobile app. And at AWS there is nobody to ask the question to without buying a support contract. But the other way exists.
What you do is use the same client id in both apps, and you don't generate a client secret. To do this you put "nil" in the clientSecret. This works fine with some caveats.
First, the AWS Mobile Hub has a bug in it's AWSCognitoUserPoolsSignInProvider. That class requires that the clientSecret is non-null. But in the SDK, the only way to tell the SDK that you want no client secret is to pass nil! However there are workarounds.
(What I did was use the AWSCUPIdPSignInProvider.swift (that I wrote), which will work fine and I have a version that will take a nil for the secret. I did that because it was faster for me to test this out. you can find that signin provider on github if you want to use it)
But a better (more future proof) solution is probably to use the AWSCognitoUserPoolsSignInProvider that the mobile hub delivers, but change the code in AWSMobileClient to configure and register your own pool rather than letting AWSCognitoUserPoolsSignInProvider do it for you.
I haven't bothered to try this, (because we only have to do it because AWS has not gotten around to updating the github aws-mobilehub-helper-ios yet). But basically in AWSMobileClient instead of this code:
func setupUserPool() {
// register your user pool configuration
AWSCognitoUserPoolsSignInProvider.setupUserPoolWithId(AWSCognitoUserPoolId, cognitoIdentityUserPoolAppClientId: AWSCognitoUserPoolAppClientId, cognitoIdentityUserPoolAppClientSecret: AWSCognitoUserPoolClientSecret, region: AWSCognitoUserPoolRegion)
AWSSignInProviderFactory.sharedInstance().registerAWSSignInProvider(AWSCognitoUserPoolsSignInProvider.sharedInstance(), forKey:AWSCognitoUserPoolsSignInProviderKey)
}
you would have something like this code
func setupUserPool() {
// register your user pool configuration
// find the service configuration (we don't know if they set it as default)
let credentialProvider = AWSCognitoCredentialsProvider(regionType: .USEast1 (or your region), identityPoolId: "YourIdentityPoolId")
let configuration = AWSServiceConfiguration(region: .USWest2 (or your region), credentialsProvider: credentialProvider)
// configure and put your own user pool in the service configuration
let userPoolConfiguration = AWSCognitoIdentityUserPoolConfiguration(clientId: AWSCognitoUserPoolAppClientId, clientSecret: nil, poolId:AWSCognitoUserPoolId)
// now we register that pool with the service configuration using the key they use
AWSCognitoIdentityUserPool.register(with: configuration, userPoolConfiguration: userPoolConfiguration, forKey: AWSCognitoUserPoolsSignInProviderKey)
AWSSignInProviderFactory.sharedInstance().registerAWSSignInProvider(AWSCognitoUserPoolsSignInProvider.sharedInstance(), forKey:AWSCognitoUserPoolsSignInProviderKey)
}
But as I said above, solution 1, use two different clients and specify two different providers is preferred.

Unauthorized when query.get() in Parse .NET SDK in worker role.

ParseClient.Initialize("id", "key");
//get the publish instance.
string publishInstanceId = msg.Split(':')[1];
var getPublishQuery = ParseObject.GetQuery("PublishInstance");
getPublishQuery.GetAsync(publishInstanceId).Wait(); //Exception raised here - System.AggregateException - Unauthorized.
My App ID and Keys are valid and I've checked it thrice. I have also used Master Key, CLient Key as well as .NET key. None of them work.
This code runs in a worker role in Windows Azure Cloud Services.
Im using 1.2.16 version of PArse .NET SDK.
Is your PublishInstance set to allow anonymous access? From the looks of the above you're not logging in, so you could be getting that error due to permissions.
Personally I would suggest creating a service account and logging in using that so you can lock your permissions down.

Primer on Getting Started

I'm just getting started with D2L and am running into problems.
On the "Getting Started" page, I have completed the first three steps:
1) Acquire an App Key/ID pair from D2L - I have received the App ID and App Key
2) Create a test account in your host LMS - I have created a new user account with the administrator role for testing
3) Choose a client library to work with - I am using the PHP SDK
4) Authenticate with your LMS - This is where I'm running into trouble.
When I use the Getting Started sample:
http://samples.valence.desire2learn.com/samples/GettingStartedSample/
And enter my host, app ID and app key and hit on the "Authenticate" button, I get a "This application is not authorized on this LMS instance. Ask your administrator to authorize this application" error.
I am an administrator on my D2L host and I'm not sure how to authorize my own app.
I have tried the following:
Navigating to the "Manage Extensibility" page because that's where D2L says my app should be located, but it isn't there.
Enabling the API (d2l.Security.Api.EnableApi) under the "DOME" page to no avail.
What am I doing wrong?
Based on your question and comments, there were two issues here:
First is that the list of App ID/Key pairs appropriate for your LMS get regularly fetched by your LMS from the D2L KeyTool service. The schedule for this fetching is once a day; accordingly, if the scheduled task isn't set up, or if your LMS isn't identifying itself properly to the KeyTool service, or if time hasn't yet elapsed after key granting to the next scheduled run of the task, the App won't yet be in your LMS' Manage Extensibility list. It sounds like you no longer have that issue.
Second is that the Valence Learning Framework APIs' authentication process (requesting and retrieving a set of user tokens for an LMS user) requires several LMS features to be properly set up: (a) the LMS must be configured to support Deep Linking, (b) the LMS must be set up to handle the ?target= parameter on incoming client URL requests, and curate that parameter throughout the user authentication process.
In cases where your LMS is not doing the user authentication but depending upon another, third-party IDP (like Shibboleth), any ?target= parameter passed into the login process must be taken care of by the IDP and properly handed back to the LMS after user authentication. In a situation where you have multiple redirections occurring during user authentication, this can involve successive generation of a target parameter, and each generation must re-URL-encode the previous request URL in its entirety (like sticking an envelope inside another envelope, inside yet another envelope).
If your LMS is not properly configured to support these two points, which you might not notice during other operations, then client calls to the Learning Framework APIs won't work because the calling client won't be able to fetch back a set of user tokens.
To solve the second of these issues, you may have to contact D2L's Customer Support desk -- they can verify, and adjust as necessary, the LMS configuration part of this authentication chain. If you're integrating your LMS with other third-party IDP components not administered or deployed by D2L, then you might also need to adjust their configurations: D2L can likely advise on what needs to be done there (curate the target parameter on URls), but cannot adjust the configuration for you in those cases.

Google API fails to authenticate when iOS client ID is used

I'm trying to integrate the Google Data API into my application. I'm using the ObjC wrapper available here:
http://code.google.com/p/gdata-objectivec-client
but I have got some issues with the authentication. Basically I'm following the steps as described here:
http://code.google.com/p/gtm-oauth2/wiki/Introduction#Signing_In_to_Google_Services
I have created a project on the API Console and added two client IDs for installed applications: one is of the "Other" platform, the other is "iOS" with the bundle ID appropriately set (though I left the appstore id 0 for the moment). Now comes the interesting part.
Both the YouTubeSample app bundled with the above wrapper library AND my iOS app work perfectly with the client ID belonging to the "Other" platform, and both of them return a 400 invalid_client error when I switch the ID for the iOS one. I have doublechecked the client IDs and secrets, all are correct. The iOS app has of course been given the correct bundle ID.
So, am I missing something trivial here?
Is there a reason that you need to use the iOS-type id/secret pair instead of the other-type pair? Perhaps I'm missing something, but the linked documentation states to not use an iOS type client id:
In the console, create a project, then click "API Access" in the left column. Create a new Client ID for an Installed Application (not a web application) type other (not iOS). This will provide Client ID and Secret strings to be used with the controller.
The controller likely doesn't identify itself as an iOS application when sending the requests, which Google probably checks when it receives an iOS id/secret pair.

Resources