Connect to Dynamics CRM 2016(On-Premise) from Android - android

I want to integrate Android application with Dynamics CRM 2015 Online and On-Premise.
For online version Connect Android App to Dynamics CRM using Web API this works fine, But ADAL dependency is not supported for OnPremise.
Are there any resources which show the basic steps to access the Microsoft CRM on-premise.
Any sample code around same for connecting to REST endpoint will be helpful.

Setup IFD for your on-premise deployment.
Authenticate to Microsoft Dynamics 365 with the Web API
When you use the Web API for Dynamics 365 (online) or an on-premises
Internet-facing deployment (IFD) you must use OAuth as described in
Connect to Microsoft Dynamics 365 web services using OAuth.
Connect to Microsoft Dynamics 365 web services using OAuth
Applies To: Dynamics 365 (online), Dynamics 365 (on-premises),
Dynamics CRM 2016, Dynamics CRM Online
The recommended authentication API for use with the Dynamics 365 Web
API is Azure Active Directory Authentication Library (ADAL), which is
available for a wide variety of platforms and programming languages.
The ADAL API manages OAuth 2.0 authentication with the Dynamics 365
web service identity provider. For more details on the actual OAuth
protocol used, see Use OAuth to Authenticate with the CRM
Service.

ADFS is required for on prem. Check this documentation for how to set up the servers. https://msdn.microsoft.com/en-us/library/dn531009(v=crm.7).aspx
If this is a one off project for a client it may also be worth creating a .Net based proxy between the app and CRM. That way you can use the .Net SDKs without worrying about losing support

On-Prem using ADAL:
public static String GetAdfs(String url) throws IOException,
ParserConfigurationException, SAXException {
URL WsdlURL = new URL(url
+ "/XrmServices/2011/Organization.svc?wsdl=wsdl0");
HttpURLConnection rc = (HttpURLConnection) WsdlURL.openConnection();
rc.setRequestMethod("GET");
rc.setDoOutput(true);
InputStreamReader read = new InputStreamReader(rc.getInputStream());
StringBuilder sb = new StringBuilder();
int ch = read.read();
while (ch != -1) {
sb.append((char) ch);
ch = read.read();
}
String response = sb.toString();
read.close();
rc.disconnect();
DocumentBuilderFactory builderFactory = DocumentBuilderFactory
.newInstance();
DocumentBuilder builder = builderFactory.newDocumentBuilder();
Document x = builder
.parse(new ByteArrayInputStream(response.getBytes()));
NodeList nodes = x.getElementsByTagName("ms-xrm:Identifier");
if (nodes.getLength() == 0)
return null;
return nodes.item(0).getFirstChild().getTextContent()
.replace("http://", "https://");
}
// ADAL init
AuthenticationContext authenticationContext = new AuthenticationContext(LoginActivity.this, GetAdfs(url), false);
authenticationContext.acquireToken(context, domain, Constants.CLIENT_ID, Constants.REDIRECT_URL, "", PromptBehavior.Auto, "", callback);
private AuthenticationCallback<AuthenticationResult> callback = new AuthenticationCallback<AuthenticationResult>() {
#Override
public void onError(Exception exc) {
ViewHelper.showToast(context, "Domain name or user not available in ms crm");
}
#Override
public void onSuccess(AuthenticationResult result) {
if (result == null || result.getAccessToken() == null || result.getAccessToken().isEmpty()) {
Toast.makeText(context, "Token is Empty", Toast.LENGTH_SHORT).show();
} else {
Log.i(Keys.TOKEN_KEY, result.getAccessToken());
}
}
};
1. On-Prem and Online using Soap
2. On-Prem and Online using ADAL

Related

How to open a url in Blackberry Access from an Android app

I have successfully opened the blackberry access from our IOS app using the url scheme access://open? , but it seems to be not working on Android. Our application is not integrated with blackberry sdk .
For anyone who needs it you can open the blackberry access from your app using the blackberry access appid com.good.gdgma.
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(urlString));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setPackage("com.good.gdgma");
try {
getApplicationContext().startActivity(intent);
}
catch(ActivityNotFoundException ex) {
showNotInstalledDialog(App.BLACKBERRY_ACCESS);
}
There is a setting the in application configuration policy for BlackBerry Access that enables or disables this feature. It's called "Allow external apps to open HTTP/HTTPS URLs through BlackBerry Access" and is set for the app config for BlackBerry Access within BlackBerry UEM. This setting applies to all non BlackBerry Dynamics methods of opening BlackBerry Access.
If you were to integrate with the BlackBerry Dynamics SDK the recommended method is to use the BlackBerry Dynamics Shared Services framework to call the Open HTTP URL Service. It's available for both iOS and Android. Here's some Android sample code to use it.
Here's a code snippet that does just that:
private static final String SERVICE_ID = "com.good.gdservice.open-url.http";
private static final String SERVICE_VERSION = "1.0.0.0";
private static final String ACCESS_ENTITLEMENT_ID = "com.good.gdgma";
private static final String HTTP_OPEN_URL_SERVICE_METHOD_NAME = "open";
....
//Get the service providers for the Open HTTP URL service.
List<GDServiceProvider> providers = GDAndroid.getInstance().getServiceProvidersFor(SERVICE_ID, SERVICE_VERSION,
GDServiceType.GD_SERVICE_TYPE_APPLICATION);
//Ensure an provider of the Open HTTP URL service was found.
if(providers == null || providers.size() == 0)
{
//No providers found.
showError("No Open HTTP URL were found.");
}
else
{
boolean foundAccess = false;
String yourURL = "www.whereEverYouWantToGo.com";
for (int count = 0; count < providers.size(); count++)
{
GDServiceProvider provider = providers.get(count);
//Ensure BlackBerry Access was found.
if (provider.getIdentifier().equalsIgnoreCase(ACCESS_ENTITLEMENT_ID))
{
foundAccess = true;
String address = providers.get(count).getAddress();
Map<String, Object> params = new HashMap<>();
params.put("url", yourURL);
try
{
//Launch BlackBerry Access.
GDServiceClient.sendTo(address, SERVICE_ID, SERVICE_VERSION,
HTTP_OPEN_URL_SERVICE_METHOD_NAME, params, null,
GDICCForegroundOptions.PreferPeerInForeground);
} catch (GDServiceException e)
{
showError(e.toString());
}
}
}
if (!foundAccess)
{
showError("BlackBerry Access not found.");
}
}

How multiple users use google cloud speech at the same time

I'm building an app that uses Google Cloud Speech.
I have a Google Service account key in my app, and I use it to call the API.
It works well when used by one user, but does not work when multiple users use it at the same time.
For example, only one user is available or all are unavailable.
The rights of the service account key are project owner.
I think it's a service account key issue...
How do I fix it?
private class AccessTokenTask extends AsyncTask<Void, Void, AccessToken> {
#Override
protected AccessToken doInBackground(Void... voids) {
final SharedPreferences prefs = mContext.getSharedPreferences(PREFS, Context.MODE_PRIVATE);
String tokenValue = prefs.getString(PREF_ACCESS_TOKEN_VALUE, null);
long expirationTime = prefs.getLong(PREF_ACCESS_TOKEN_EXPIRATION_TIME, -1);
// Check if the current token is still valid for a while
if (tokenValue != null && expirationTime > 0) {
if (expirationTime > System.currentTimeMillis() + ACCESS_TOKEN_EXPIRATION_TOLERANCE) {
return new AccessToken(tokenValue, new Date(expirationTime));
}
}
final InputStream stream = mContext.getResources().openRawResource(R.raw.credential);
try {
final GoogleCredentials credentials = GoogleCredentials.fromStream(stream).createScoped(SCOPE);
final AccessToken token = credentials.refreshAccessToken();
prefs.edit()
.putString(PREF_ACCESS_TOKEN_VALUE, token.getTokenValue())
.putLong(PREF_ACCESS_TOKEN_EXPIRATION_TIME, token.getExpirationTime().getTime())
.apply();
return token;
} catch (IOException e) {
Log.e(TAG, "Failed to obtain access token.", e);
}
return null;
}
#Override
protected void onPostExecute(AccessToken accessToken) {
mAccessTokenTask = null;
final ManagedChannel channel = new OkHttpChannelProvider()
.builderForAddress(GOOGLE_API_HOSTNAME, GOOGLE_API_PORT)
.nameResolverFactory(new DnsNameResolverProvider())
.intercept(new GoogleCredentialsInterceptor(new GoogleCredentials(accessToken)
.createScoped(SCOPE)))
.build();
mApi = SpeechGrpc.newStub(channel);
// Schedule access token refresh before it expires
if (mHandler != null) {
mHandler.postDelayed(mFetchAccessTokenRunnable,
Math.max(accessToken.getExpirationTime().getTime() - System.currentTimeMillis() - ACCESS_TOKEN_FETCH_MARGIN, ACCESS_TOKEN_EXPIRATION_TOLERANCE));
}
}
}
This code is the code that calls 'credential.json' file on Android and gets 'Access token'.
The server for this app is python and communicates via http.
https://github.com/GoogleCloudPlatform/android-docs-samples/tree/master/speech/Speech
The description in the link above tells you to delegate the authentication to the server.
I want to write that part with python code.
What should I do?
In the link you provided in the description, they suggest you to read first the basic authentication concepts document. In your case, use a service account for the Android application.
I understand that you have already been able to provide end user credentials to a Google Cloud Platform API, as for example Cloud Speech API.
If you want to authenticate multiple users to your application you should use instead Firebase authentication. The link contains a brief explanation and a tutorial.
There are several Python client libraries for GCP that you can use, depending on what operations do you want to perform on the server. And regarding Python authentication on the server side, this documentation shows how the authentication for Google Cloud Storage works (have this example in mind as a reference).

Android: What is transport and jsonFactory in GoogleIdTokenVerifier.Builder?

in the blow code, whats is transport and jsonFactory ? (I do not understand)
https://developers.google.com/identity/sign-in/android/backend-auth#using-a-google-api-client-library
import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken;
import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken.Payload;
import com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier;
...
GoogleIdTokenVerifier verifier = new GoogleIdTokenVerifier.Builder(transport /**Here**/, jsonFactory /**Here**/)
.setAudience(Arrays.asList(CLIENT_ID))
// If you retrieved the token on Android using the Play Services 8.3 API or newer, set
// the issuer to "https://accounts.google.com". Otherwise, set the issuer to
// "accounts.google.com". If you need to verify tokens from multiple sources, build
// a GoogleIdTokenVerifier for each issuer and try them both.
.setIssuer("https://accounts.google.com")
.build();
// (Receive idTokenString by HTTPS POST)
GoogleIdToken idToken = verifier.verify(idTokenString);
if (idToken != null) {
Payload payload = idToken.getPayload();
// Print user identifier
String userId = payload.getSubject();
System.out.println("User ID: " + userId);
// Get profile information from payload
String email = payload.getEmail();
boolean emailVerified = Boolean.valueOf(payload.getEmailVerified());
String name = (String) payload.get("name");
String pictureUrl = (String) payload.get("picture");
String locale = (String) payload.get("locale");
String familyName = (String) payload.get("family_name");
String givenName = (String) payload.get("given_name");
// Use or store profile information
// ...
} else {
System.out.println("Invalid ID token.");
}
Since all the other answers are blah blah blah, here's a short answer:
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.gson.GsonFactory;
GoogleIdTokenVerifier verifier =
new GoogleIdTokenVerifier.Builder(new NetHttpTransport(), new GsonFactory());
The GoogleIdTokenVerifier.Builder returns a GoogleIdTokenVerifier that will make a request to the tokeninfo endpoint with the transport you give it and use the JSONFactory to create a parser to parse the response.
Here is an example of an authenticator for a Cloud Endpoints project that uses the GoogleIdTokenVerifier.Builder
public class GoogleAuthenticator implements Authenticator {
private static final Logger log = Logger.getLogger(GoogleAuthenticator.class.getName());
private static final JacksonFactory jacksonFactory = new JacksonFactory();
// From: https://developers.google.com/identity/sign-in/android/backend-auth#using-a-google-api-client-library
// If you retrieved the token on Android using the Play Services 8.3 API or newer, set
// the issuer to "https://accounts.google.com". Otherwise, set the issuer to
// "accounts.google.com". If you need to verify tokens from multiple sources, build
// a GoogleIdTokenVerifier for each issuer and try them both.
GoogleIdTokenVerifier verifierForNewAndroidClients = new GoogleIdTokenVerifier.Builder(UrlFetchTransport.getDefaultInstance(), jacksonFactory)
.setAudience(Arrays.asList(CRLConstants.IOS_CLIENT_ID, CRLConstants.ANDROID_CLIENT_ID_RELEASE, CRLConstants.ANDROID_CLIENT_ID_DEBUG))
.setIssuer("https://accounts.google.com")
.build();
GoogleIdTokenVerifier verifierForOtherClients = new GoogleIdTokenVerifier.Builder(UrlFetchTransport.getDefaultInstance(), jacksonFactory)
.setAudience(Arrays.asList(CRLConstants.IOS_CLIENT_ID, CRLConstants.ANDROID_CLIENT_ID_RELEASE, CRLConstants.ANDROID_CLIENT_ID_DEBUG))
.setIssuer("accounts.google.com")
.build();
// Custom Authenticator class for authenticating google accounts
#Override
public User authenticate(HttpServletRequest request) {
String token = request.getHeader("google_id_token");
if (token != null) {
GoogleIdToken idToken = null;
try {
idToken = verifierForNewAndroidClients.verify(token);
if(idToken == null) idToken = verifierForOtherClients.verify(token);
if (idToken != null) {
GoogleIdToken.Payload payload = idToken.getPayload();
// Get profile information from payload
String userId = payload.getSubject();
String email = payload.getEmail();
return new GoogleUser(userId, email);
} else {
log.warning("Invalid Google ID token.");
}
} catch (GeneralSecurityException e) {
log.warning(e.getLocalizedMessage());
} catch (IOException e) {
log.warning(e.getLocalizedMessage());
}
}
return null;
}
}
You need to select transport according to the platform on which you are running the code.
Quoting from the documentation
Implementation is thread-safe, and sub-classes must be thread-safe. For maximum efficiency, applications should use a single globally-shared instance of the HTTP transport.
The recommended concrete implementation HTTP transport library to use depends on what environment you are running in:
Google App Engine: use com.google.api.client.extensions.appengine.http.UrlFetchTransport.
com.google.api.client.apache.ApacheHttpTransport doesn't work on App Engine because the Apache HTTP Client opens its own sockets (though in theory there are ways to hack it to work on App Engine that might work).
com.google.api.client.javanet.NetHttpTransport is discouraged due to a bug in the App Engine SDK itself in how it parses HTTP headers in the response.
Android:
For maximum backwards compatibility with older SDK's use newCompatibleTransport from com.google.api.client.extensions.android.http.AndroidHttp (read its JavaDoc for details).
If your application is targeting Gingerbread (SDK 2.3) or higher, simply use com.google.api.client.javanet.NetHttpTransport.
Other Java environments
com.google.api.client.javanet.NetHttpTransport is based on the HttpURLConnection built into the Java SDK, so it is normally the preferred choice.
com.google.api.client.apache.ApacheHttpTransport is a good choice for users of the Apache HTTP Client, especially if you need some of the configuration options available in that library.
Documentation Link: https://developers.google.com/api-client-library/java/google-http-java-client/reference/1.19.0/com/google/api/client/http/HttpTransport?is-external=true
If you blindly follow the 2nd answer to the question, you will get the exception Caused by: java.lang.ClassNotFoundException: com.google.appengine.api.urlfetch.HTTPMethod
JacksonFactory is deprecated. So this works.
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.gson.GsonFactory;
GoogleIdTokenVerifier verifier = new GoogleIdTokenVerifier.Builder(new NetHttpTransport(), new GsonFactory())
.setAudience(Arrays.asList(CRLConstants.IOS_CLIENT_ID, CRLConstants.ANDROID_CLIENT_ID_RELEASE, CRLConstants.ANDROID_CLIENT_ID_DEBUG))
.setIssuer("accounts.google.com")
.build();

Android - unable to use OAuth access token to retrieve Google Reader feeds

I need to obtain OAuth2 authentication token to pass it to the server so it can fetch list of Google Reader feeds for the user. Server is .NET - I have no access to it or to it's code but most likely it is using unofficial Reader API
I was able to use Android Account manager to obtain valid token for this purpose with the following code (notice that authTokenType="reader")
Account account = accounts[0];
manager.getAuthToken(account, "reader", null, this, new AccountManagerCallback<Bundle>() {
public void run(AccountManagerFuture<Bundle> future) {
try {
// If the user has authorized your application to use the tasks API
// a token is available.
String token = future.getResult().getString(AccountManager.KEY_AUTHTOKEN);
// Now you can send the token to API...
cacheManager.putString(GOOGLE_AUTH, token);
GoogleReaderManager.startAddFeedActivity(AddGoogleReaderSourcesActivity.this);
finish();
} catch (OperationCanceledException e) {
Log.e(TAG, "User cancelled", e);
finish();
} catch (Exception e) {
Log.e(TAG, "Failed to obtain Google reader API_KEY", e);
}
}
}, null);
The code above works fine when I send token to the server side .Net app: the app is able to retrieve the list of Reader feeds.
The problem is that this only works for "Google inside" devices. On Nook I have no such luck since there's no way that I was able to find to add Google account to the account manager. So I'm trying to it using OAuth 2 protocol as described here
It works fine as far as obtaining the token: User approves the app from the mobile page which returns the code token which then mobile app exchanges for the Auth token. However this token will not work with the server process. I have a feeling that perhaps I'm using the wrong scope in this URL:
https://accounts.google.com/o/oauth2/auth?response_type=code&scope=https://www.google.com/reader/api/0/subscription/list&redirect_uri=http://localhost&approval_prompt=force&state=/ok&client_id={apps.client.id}
Scopes that I did try in various combinations:
https://www.google.com/reader/api
https://www.google.com/reader/api/0
https://www.google.com/reader/api/0/subscription/list
https://www.google.com/reader/api+https://www.google.com/reader/atom
Here's example of JSON that is returned from get token POST
{"expires_in":3600,
"token_type":"Bearer",
"access_token":"ya29.AHES6ZSEvuUb6Bvd2DNoMnnN_UnfxirZmf_RQjn7LptFLfI",
"refresh_token":"1\/bUwa5MyOtP6VyWqaIEKgfPh08LNdawJ5Qxz6-qZrHg0"}
Am I messing up scope or token type? Not sure how to change a token type. Any other ideas?
P.S. Google account login page asks: Manage your data in Google Reader, that's why I suspect that the scope is wrong
I got it working for https://www.google.com/reader/api/0/subscription/list. So thought of sharing with you.
I have valid access_token:
This is what i tried to resolve it (partially) :
Google provides OAuth 2.o playgound; where they actually simulate all aspects of OAuth 2.0 as well as final API call to fetch data.
I found this very helpful as it clearly shows what is being sent to request.
Here is the URL : https://developers.google.com/oauthplayground/
Using this, i tweaked my api call below and it works :)
public static String getReaderContent(String accessToken){
String url = "https://www.google.com/reader/api/0/subscription/list" ;
HttpClient client = new HttpClient();
GetMethod method = new GetMethod(url);
String response="";
method.setRequestHeader("Authorization", "OAuth "+accessToken);
try {
int statusCode = client.executeMethod(method);
String response= method.getResponseBodyAsString();
System.out.println("response " + responseStr);
} catch (HttpException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return response;
}
So this works properly fine for getting subscription list; but have not been able to make it work for reader api which you have mentioned in your question.
Let me know if you have got way around google reader API.

how to sign out in LinkedIn using authrequest using android?

i developed one app integrated with linkedIn..!
i do SignIn authentication in linkedIn using OAuth Service to post the Network Update..but now how to sign out (de-authenticate) to the LinkedIn automatically?
Thanks in adv..
As per the official blog
Token Invalidation
Now you can invalidate an OAuth token for your application. Just send an OAuth signed GET request to:
https://api.linkedin.com/uas/oauth/invalidateToken
A 200 response indicates that the token was successfully invalidated.
However as per this :
Third party applications do not have any way to log a user out from
LinkedIn - this is controlled by the website. Invalidating the token
makes the user re-authorize the next time they try to use the
application, but once they have logged into LinkedIn their browser
will remain logged in until they log out via the website.
So In conclusion : as of this date of writing, Linked In does not give this support to 3rd Party Applications
Reading your question i have also tried to find solution and also talked to Mr. Nabeel Siddiqui - Author of linkedin-j API
and this was his reply when i asked if it's possible to sign out using linkedin-j api?
Hi Mayur
There is a method LinkedInOAuthService#invalidateAccessToken that is supposed to invalidate your access token. Its not used much by the community so I am not sure if it works as expected or not. Do try it and let me know if there are problems.
Regards
Nabeel Mukhtar
so in my activity i tried it using this way.
final LinkedInOAuthService oAuthService = LinkedInOAuthServiceFactory.getInstance().createLinkedInOAuthService(consumerKey, consumerSecret);
final LinkedInApiClientFactory factory = LinkedInApiClientFactory.newInstance(consumerKey, consumerSecret);
LinkedInRequestToken liToken;
LinkedInApiClient client;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
liToken = oAuthService.getOAuthRequestToken(CALLBACKURL);
Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(liToken.getAuthorizationUrl()));
startActivity(i);
}
#Override
protected void onNewIntent(Intent intent)
{
super.onNewIntent(intent);
Uri uri = intent.getData();
if (uri != null && uri.toString().startsWith(CALLBACKURL))
{
String verifier = intent.getData().getQueryParameter("oauth_verifier");
LinkedInAccessToken accessToken = oAuthService.getOAuthAccessToken(liToken, verifier);
client = factory.createLinkedInApiClient(accessToken);
Connections con = client.getConnectionsForCurrentUser();
//AFTER FETCHING THE DATA I HAVE DONE
oAuthService.invalidateAccessToken(accessToken);
//this is for sign out
}
}
Please, Try this way once and tell me if it solves your problem.
cause I have also donwloaded and seen the SourceCode for linkedin-j API and in
LinkedInOAuthServiceImpl.java
they have given the function and that function also works if we write the same code in our file.
that is,
#Override
public void invalidateAccessToken(LinkedInAccessToken accessToken) {
if (accessToken == null) {
throw new IllegalArgumentException("access token cannot be null.");
}
try {
URL url = new URL(LinkedInApiUrls.LINKED_IN_OAUTH_INVALIDATE_TOKEN_URL);
HttpURLConnection request = (HttpURLConnection) url.openConnection();
final OAuthConsumer consumer = getOAuthConsumer();
consumer.setTokenWithSecret(accessToken.getToken(), accessToken.getTokenSecret());
consumer.sign(request);
request.connect();
if (request.getResponseCode() != HttpURLConnection.HTTP_OK) {
throw new LinkedInOAuthServiceException(convertStreamToString(request.getErrorStream()));
}
} catch (Exception e) {
throw new LinkedInOAuthServiceException(e);
}
}

Categories

Resources