How to consume the login returned object 'LoginFunctions' - priority-web-sdk

According to the SDK,
The 'LoginFunctions' = This object is returned after a successful login to the server. Use the following methods for this object to retrieve information regarding the Priority installation and API.
But the login function does not return any object.
Can you explain how to consume the object ?
As you can see from my code, the result is not defined.
enter image description here

In the image you attached, the breakpoint you are paused on and the "result" parameter are not in the same function scope. Do you get a result if you stop on line 140?
Please share your console output after the login.
You can also check the network tab and see if you are getting any results from the server. If the login is successful you should see results which would be parsed and retrieved as a promise by the SDK.

Related

Restore a 1:1 conversation in Skype Web SDK

Is it possible to restore a 1:1 conversation?
The Conversation object in the Skype SDK seems to have such functionality. You should be able to restore a conversation by passing a href to it. But when I pass a href string as parameter to createConversation it throws the following error:
Error: ResourceNotFound
at Error (native)
at Exception (http://.../SkypeSDK.js:3346:31)
at UCWA.get (http://.../SkypeSDK.js:15141:31)
at init (http://.../SkypeSDK.js:40672:50)
at new Conversation (http://.../SkypeSDK.js:41826:25)
at createConversationModel (http://.../SkypeSDK.js:41963:36)
at BaseModel.createConversation (http://.../SkypeSDK.js:42037:48)
The lines can be a little bit off. I modified the createConveration method to pass the href to Conversation.
The href string has this format:
/ucwa/oauth/v1/applications/xxxxxxxxxxxx/communication/conversations/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
We have the following situation:
One site has the normal SDK and waits for incoming calls. If you accept the call you should be redirected to a site with the SDK+CC and answer the call. Now we are stuck at how to pass the call. We also tried with it getConversation, but it doesn't return the last incoming conversation.
Once you accept a call on one endpoint you can transfer it to another endpoint. However you cannot accept a call and then re-answer it on a different endpoint. Also, answering the call starts the process of connecting media so that endpoint has effectively picked up the call.
The href of each conversation is unique per application, and in your scenario you will have one for each site. These cannot be shared between applications.

ADALiOS - how to refresh accessToken silently?

I'm using ADALiOS v3.0.0-pre.2 to connect to Azure AD B2C and authorize a given user. I successfully obtain an accessToken for the user, who gets prompted with UI to login in the process. I use the acquireTokenWithScopes method on ADAuthenticationContext instance to do so.
Somewhere down the line, I want to make sure that the accessToken I obtained earlier is still valid and hasn't been revoked. So, I use acquireTokenSilentWithScopes to check. However, I get an immediate error back saying:
Error raised: 10. Additional Information: Domain: ADAuthenticationErrorDomain Details: The user credentials are need to obtain access token. Please call the non-silent acquireTokenWithResource methods.
What's the right usage of this API such that the token gets silently refreshed or throws an error only when it has been revoked on the server side?
I've managed to beat acquireTokenSilentWithScopes into submission by making the following changes to ADALiOS v3.0.0-pre.2.
Change #1:
ADUserIdentifier has the following class method:
+(BOOL) identifier:(ADUserIdentifier*)identifier matchesInfo:(ADProfileInfo*)info
In it, there are the following lines of code:
NSString* matchString = [identifier userIdMatchString:info];
if (!matchString || [matchString isEqualToString:identifier.userId])
{
return YES;
}
For one reason or another, matchString can sometimes come back as NSNull and calling isEqualToString: method on it will throw. I changed it thusly:
id matchString = [identifier userIdMatchString:info];
if (!matchString || ![matchString isKindOfClass:[NSString class]] || [matchString isEqualToString:identifier.userId])
{
return YES;
}
This seems like a legit bug in the framework that's worth fixing.
Change #2:
When a token is received from AD, ADALiOS tries to store that value in the cache. At some point, it calls ADTokenCacheStoreItem's userCacheKey property, which is defined as follows:
-(NSString*)userCacheKey
{
switch (_identifierType)
{
case OptionalDisplayableId:
case RequiredDisplayableId:
return _profileInfo.username;
case UniqueId:
return _profileInfo.subject;
}
}
In my case, I use RequiredDisplayableId to identify users. In the switch statement above, that translates to _profileInfo.username, which, in turn, returns the preferred_username value from the user profile dictionary. For me that value is not set. So, userCacheKey returns NSNull and the caching mechanism fails.
The values that are set in the user profile dictionary are name and tid. This could be a server misconfiguration, but I worked around the issue by changing the return value of this method to _profileInfo.friendlyName (which maps to name in the user profile dictionary).
Change #3:
The ADKeychainTokenCacheStore, which I use as the concrete ADTokenCacheStoring cache of choice, exposes a sharedGroup property that allows multiple applications to share common keychain secrets. By default, sharedGroup is set to com.microsoft.adalcache. However, since the class is currently private, there is no way to override this value. Also, having that value set requires the iOS app to declare the shared group name in its entitlements. Without these entitlements properly configured, setting values into the keychain fails. So, to work around this issue, I manually set the default sharedGroup value to nil in the ADKeychainTokenCacheStore class itself. I suspect eventually this class will be exposed by the framework as public, but currently that's not the case so I had to hack into it.
Change #4
When I request an auth token from the AD server via the ADALiOS framework, I do so using a policy and a set of scopes. The framework code uses this policy/scope pair to create a lookup key and see if any tokens for that key have already been cached. If none are found, the code contacts the server as expected. Once the server returns an auth token, the framework attempts to cache the value. It constructs a brand new policy/scope key object. However, this time, it uses the policy and scope values that are returned by the server, not the ones I passed in. And, for some reason, the server returns those values to nil. As a result, the new policy/scope key that gets constructed for storage is valid but different from the one I used to look up the cached token initially. So, while the caching operation succeeds, next time I try to look up the auth token using my valid policy/scope pair, the lookup fails.
This may, once again, be a server misconfiguration issue.
Regardless, to fix the problem, I now reset the policy and scope values in the response from the server to the original values I used to generate the server request in the first place. This happens in the following method in ADAuthenticationContext(TokenCaching):
- (void)updateCacheToResult:(ADAuthenticationResult*)result
cacheInstance:(id<ADTokenCacheStoring>)tokenCacheStoreInstance
cacheItem:(ADTokenCacheStoreItem*)cacheItem
withRefreshToken:(NSString*)refreshToken
After all these changes, getting the AD auth token and refreshing it silently seems to work as expected. I'm a little worried about how much I needed to hack into the codebase to make it work. It would be helpful if some MS folks could direct me as to whether these changes were warranted or whether there is a more straight-forward solution.
UPDATE:
It turns out that you don't need to hack into ADKeychainTokenCacheStore directly (change #3 above). The ADAutheticationSettings class exposes a method for you to do so thusly:
[[ADAuthenticationSettings sharedInstance] setSharedCacheKeychainGroup:nil];
I'm Brandon Werner from the Azure Active Directory team. I answered this question here: https://stackoverflow.com/a/44170226/1232116 for the specific question asked.

which tokens/codes/ids actually need to be exchanged for google oauth

i'm trying to follow the example code on google's website here, but it seems a little broken - the javascript references getting a list of people from the server, but in the server-side code there's no reference to calling those functions of the api, it just returns an HTTP status code and a text status, so i'm wondering if there's a step missing and i'm exchanging the wrong code at the wrong time.
my current flow is
login button button clicked, magic happens, my callback gets passed an object with a whole bunch of properties in it
I take the code property from that object, and post it back to my server in an ajax request
on my server, i run the following python, where auth_code_from_js is the data of my post request:
oauth_flow = client.flow_from_clientsecrets('client_secrets.json', scope='')
credentials = oauth_flow.step2_exchange(auth_code_from_js)
python throws a FlowExchangeError with the message invalid request and no other useful information
am i missing a step? is that initial 'code' property what i'm supposed to be passing in to the 'step2_exchange' method?

State is invalid after logging in

I was struggling to find the correct way of implementing OAuth with Google API and finally managed to get it working by implementing a DataStore to manage the users access tokens.
However it has now stopped working, and by that I mean once the code has redirected me to Google and I've selected a profile and authorized the app to access the requested information my app throws a TokenResponseException
Server Error in '/' Application.
Error:"State is invalid", Description:"", Uri:""
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: Google.Apis.Auth.OAuth2.Responses.TokenResponseException: Error:"State is invalid", Description:"", Uri:""
What I have noticed is that the FileDataStore I passed to IAuthorizationCodeFlow is no longer creating files in the specified directory. Where as before it was creating a file with a name similar to System.String-oauth_5f798cfd-0d9a-42ad-a05b-567fda21d916 which was just a text file with my url inside of it.
For clarity the url which throws this error is https://myurl.net/AuthCallback/IndexAsync?state=https://myurl.net/dashboard32977907&code=4/PAtdUBSV4noqSna3j5ELkan0eOel.wu5woMyVz9kWYKs_1NgQtmV75cIkiQI
The error means that the state parameter that Google sent back to your application is not the same one that you sent (considering the comparison is being done correctly).
I don't know how you are creating the authentication URL (the one that points to the Google server), but I think you should url-encode the state param.
https%3A%2F%2Fmyurl.net%2Fdashboard32977907
instead of
https://myurl.net/dashboard32977907
This usually happens when the value of userId changes between the authorization steps/redirects.
For example, if you use Session.SessionID as the userId, and don't store anything in the session, ASP.NET changes the SessionID with each request.
By userId, I mean the first parameter of methods like GoogleAuthorizationCodeFlow.ExchangeCodeForTokenAsync() or AuthorizationCodeWebApp.AuthorizeAsync().

DotNetOpenAuth oAuth2 Message already been processed

I'm discovering dotnetopenauth and trying to use it with the oauth2 ctp release.
I must be stupid but it's very complicate to get it working for me.
So after a lot of tests I'm stuck at some point.
So my app wants to get an access token. My app callback is http://localhost/myapp/accept.aspx?...
My oauth server is http://localhost/oauth/
My app ask for the code. The server display a login page. I log in. Then it asks if I want to give access to my app. I said yes.
My app get a response with a code key. So my app request the token to my oauth. And when my oauth executes the line :
public ActionResult Token()
{
var request = this.authorizationServer.ReadAccessTokenRequest();
I got the error "message already processed. maybe a replay attack..."
So I try to understood what happened. I can't play with the source code because the version on git is not the same (the interface icryptostore not found, you get a list of callback url and not only one, ...).
If someone can explain me exactly what is happening. From what I read it's because it must be a second webresponse, but as it's the entry pf the controller, I don't know what I'm missing.
Hope I gave you enough infos.
Thanks in advance for your help.
M.
Edited : I copy paste the wrong action call. It's the "Token" function.
You likely have two places that are trying to respond to the access token request. The one that's failing would be the second one. You should only have one place parsing this request to avoid this false "replay attack" error.
You presumably have an INonceStore implementation in your project. Set a breakpoint in the StoreNonce method then repro the problem. You'll likely see two hits to the StoreNonce method. You'll be able to observe the callstacks of both calls to determine which one you want to keep and which one to delete.

Resources