Connecting to SharePoint online using CSOM in a Windows Store App - windows-8

I want toe make my windows 8.1 store app, which communicates with SharePoint 2013, compatible with SharePoint online. This is my code so far:
var context = new ClientContext(siteUrl);
try
{
Regex rgx = new Regex(#"#");
if (rgx.IsMatch(CredentialHelper.GetSharePointCredentialsFromVault().UserName))
{
context.Credentials =
new SharePointOnlineCredentials(
CredentialHelper.GetSharePointCredentialsFromVault().UserName,
CredentialHelper.GetSharePointCredentialsFromVault().Password);
}
else
{
context.Credentials = CredentialHelper.GetSharePointCredentialsFromVault();
}
var site = context.Web;
context.Load(site);
await context.ExecuteQueryAsync();
isLoggedIn = true;
}
So, when there is an '#' character in the username I asume for now it's targeting a SharePoint online environment and uses SharePointOnlineCredentials. otherwise it uses SharePoint on premise credentials.
If I type in my SharePoint online creds, it keeps showing an exception which says "The sign-in name or password does not match one in the Microsoft account system.". I'm sure I did type in the right creds...
Can any one help me with this?
Thanks in advance.

I do not have the direct answer, but faced the same error message when trying to login with the PowerShell. It turned out that I had not yet installed the SharePoint cmdlets. After loading them as indicated here it worked for me. Maybe this helps you.

Related

Why do my queries work in Microsoft Graph Explorer but not in my client app (MVC C#)?

I am attempting to learn more about Microsoft Graph and have made extensive use of the Microsoft Graph Explorer site. I am now attempting to transfer a pair of queries from Microsoft Graph Explorer to an MVC C# app but I am receiving the following error message:
"AADSTS65001: The user or administrator has not consented to use the application with ID '' named 'My App'."
The following query works just fine in Microsoft Graph Explorer:
https://graph.microsoft.com/v1.0/servicePrincipals/[resourceID]/appRoleAssignedTo?$select=appRoleId,principalId,principalDisplayName,principalType,resourceId,resourceDisplayName
The following C# equivalent throws the error:
var appRoleAssignedTo = await graphClient.ServicePrincipals[resourceId].AppRoleAssignedTo
.Request()
.Select("appRoleId,principalId,principalDisplayName,principalType,resourceId,resourceDisplayName")
.GetAsync()
.ConfigureAwait(false);
The Microsoft Graph Explorer site indicates the following four permissions must be consented by the app administrator:
"Application.Read.All", "Application.ReadWrite.All", "Directory.Read.All", "Directory.ReadWrite.All".
These permissions have been consented as required.
I am trying to automate these queries so that I can incorporate them into my app. Any assistance is greatly appreciated.
I think you may forget to grant api permission, or setting delegate api permission but using client credential flow to call the api.
when we use Microsoft Graph Explorer to call graph api, it require us to sign in with the microsoft account first, then we can call the api, this means we are using delegate api permission to call the api.
So I want to double confirm with you that if you has a sign in progress before you call the api, if not, then the failure should be the expected behavior. If you don't want to sign in before calling graph api, you need to grant application api permission and using client credential flow like code below to call this api:
var scopes = new[] { "https://graph.microsoft.com/.default" };
var tenantId = "tenant_name.onmicrosoft.com";
var clientId = "azure_ad_appid";
var clientSecret = "client_secret";
var clientSecretCredential = new ClientSecretCredential(
tenantId, clientId, clientSecret);
var graphClient = new GraphServiceClient(clientSecretCredential, scopes);
If you has a sign in progress before calling the api, then I suggest you to check if you've grant the api permission, if you want to give application api permission, you also need to click this button.

Getting all messages from Microsoft Teams

I'm trying to get all the messages from Microsoft Teams in my tenant, I have registered the application to Azure, set the correct permissions and grated admin privileges.
What I am getting confused about is creating a GraphServiceClient.
My app is more of an Daemon Application.
I would really appreciate if someone could give me an example of how to create the client correctly.
this is my code so far:
string[] graphScopes = { "https://graph.microsoft.com/.default" };
IConfidentialClientApplication app = ConfidentialClientApplicationBuilder
.Create("x")
.WithTenantId("x")
.WithClientSecret("x")
.Build();
ClientCredentialProvider authProvider = new ClientCredentialProvider(app);
GraphServiceClient graphClient = new GraphServiceClient(authProvider);
try
{
var messages = await graphClient.Teams["x"].Channels["x#thread.skype"].Messages.Request().GetAsync();
Console.ReadLine();
foreach(var item in messages)
{
Console.WriteLine(item.Body);
}
}
catch(Exception e)
{
Console.WriteLine(e.Message);
Console.Read();
}
I'm getting the following error no matter what I'm trying to get
Code: UnknownError Inner error: AdditionalData: request-id: x date: 2020-05-27T14:22:37 ClientRequestId:x
update: I was able to get something from the API, I had wrong permissions.
still can't get the messages though,
I have all these permission:
ChannelMessage.Read.All, Group.Read.All, Group.ReadWrite.All
I'm probably missing the "ChannelMessage.Read.Group (RSC)" permission but I can't find it in the permissions page.
May this is the solution or the problem ;-)
Microsoft Teams APIs in Microsoft Graph that access sensitive data are considered protected APIs. These APIs require that you have additional validation, beyond permissions and consent, before you can use them.
https://learn.microsoft.com/en-us/graph/teams-protected-apis
Your problem is you are accessing a "beta" api but using the production base url path.
The permission you need is ANY of the following (i.e. or not and):
ChannelMessage.Read.Group (RSC) OR
ChannelMessage.Read.All OR
Group.Read.All OR
Group.ReadWrite.All
Since you have Group.Read.All, that is ALL you need for permissions.
What you need to do is change the base URL to the beta api:
graphClient.BaseUrl = "https://graph.microsoft.com/beta";
UPDATED:
Since now you are saying that you are getting a "Forbidden" error, I think you also have a consent problem.
My guess is that you created & consented you app on one tenant but you are trying to access the data in another tenant. This will give you a forbidden errors. i.e. you created and consented on a dev azure account tenant and are trying to access your work tenant.
If this is the situation you need to:
* Make sure that the setup you azure app to be multi-tenanted
* You have to get your app consented by the target tenant
If you do that and use the beta endpoint I would expect that your example code will start working.
Update2:
Finally got around to trying to do the message list with a application context like you above and I get the same Forbidden error as well from the beta api. From a user context it works fine. So your answer will be to use a user context and not an application context to access this API.
It looks like what you are hitting is a Protected API. So if you want to use this API from an application context, you will have to submit a request to be allowed access to it.

Authenticate Google access token with ASP.NET Core backend server

I have Angular2 on client and ASP.NET Core on server side. I use JavaScriptServices (aspnetcore-spa template).
For authentication I use OpenIddict and I follow example here.
Now I am on the server side in Controller class method and I would like to validate id_token because this is suggested on this side:
Important: Do not use the Google IDs returned by getId() or the user's
profile information to communicate the currently signed in user to
your backend server. Instead, send ID tokens, which can be securely
validated on the server.
And I would also like to register user (save email, profile ...) in my database through ASP.NET Core identity.
I would like to use Google API client Library for .NET to get user information and store refresh_token. Years ago I manage to do it with PHP, but I can't figure it out with .NET.
I download nuget packages: Google.Apis, Google.Apis.OAuth2.v2, Google.Apis.Plus.v1.
I am not sure which nuget package I need for this, which class should I use, how to set Google ServerKey and how to get user information from information which I get from gapi.signin2 button.
In simple:
How can I validate id_token from .NET with Google .NET Client library?
I found solution here. It is old, but it works.
var googleInitializer = new BaseClientService.Initializer();
googleInitializer.ApiKey = this.config["Authentication:Google:ServerKey"];
Oauth2Service ser = new Oauth2Service(googleInitializer);
Oauth2Service.TokeninfoRequest req = ser.Tokeninfo();
req.AccessToken = request.AccessToken; //access token received from Google SignIn button
Tokeninfo userinfo = await req.ExecuteAsync();
I didn't figure it out how to get Display name and picture on server. But it can be done on client:
onGoogleLoginSuccess(user: gapi.auth2.GoogleUser)
{
console.log("basic profile", user.getBasicProfile());
}
If someone knows more updated solution or how to retrieve basic user profile on server, please share it.
In addition I can use Google+, but careful because Google Account is not Google+ Account. I didn't have + account and get error:
Google.Apis.Requests.RequestError Not Found [404] Errors [
Message[Not Found] Location[ - ] Reason[notFound] Domain[global] ]
in code:
var plusService = new PlusService(googleInitializer);
Person me = await plusService.People.Get(userinfo.UserId).ExecuteAsync();
but it is possible to get all user information (picture, display name, first name, last name, birthday ...)

DotNetOpenAuth 4.3 and Google - OpenID 2.0 + OAuth 1.0 deprecated

If you want to cut to the chase, the question is: what is the best/official way to use DotNetOpenAuth with Google in asp.net mvc 5?
About a year ago, I used OAuth (DotNetOpenAuth oAuth and OpenID) pretty much as it came out of the box for asp.net MVC 4 (as it is in the sample project). Since then I used it successfully for google, facebook, yahoo and microsoft. However, recently I have been having intermittent problems with users signing into google. I have tried upgrading to MVC 5 and DotNetOpenAuth 4.3, but I get the same.
When I looked at the google docs I found this:
Important: Google has deprecated its support for OAuth 1.0. If you are
using OpenID 2.0 + OAuth 1.0, we recommend that you switch to Google+
Sign-In. Google+ Sign-In provides the OAuth 2.0 authentication
mechanism with rich social features and access to additional Google
desktop and mobile features. It supports all Google users and
transparent migration. For details, see the Migration of Google
authentication.
I could very well be mistaken, by I thought that out-of-the-box asp.net mvc 4 DotNetOpenAuth uses OpenID 2.0 (I use minimumRequiredOpenIdVersion="V20") + OAuth 1.0. I can see in the DotNetOpenAuth source that there is an OAuth 2.0 library under 'product', but I am not sure how to use this. Also, I am a bit nervous about Auth 2.0 as what I have read is not very complementary and it seems that it is easier to shoot oneself in the foot (might be unfounded, but it seems to be a recurring theme).
For Google+ I found these instructions which seem pretty straightforward, but that is almost a year ago, so I am wondering if this is still the best way to go. I also found this git repository implementing Google oauth2. Still, I would like to know whether this is still relevant as it is all from some time ago.
So, the question is - what is the best/official way to use DotNetOpenAuth with Google in asp.net mvc5? Hopefully I haven't missed anything obvious, in which case just a pointer to some links will be fine.
Update
I found this question and this question which are related. I guess that I will go with the google auth2 from git unless I am told otherwise.
Resolution
I did the following: -
Followed the steps in the link provided by the accepted answer. It is this link.
It's important to keep using SSL after login and not drop back to HTTP, your login cookie is just as secret as your username and password…redirecting back to HTTP after you’re logged in won’t make the current request or future requests much faster.
Got the latest DotNetOpenAuth.GoogleOAuth2 on Nuget.
I looked at the recommendation from this msdn blog (by the same author) about how to best to secure the site. Basically, the recommendation is to add the following which will force all pages to HTTPS:
filters.Add( new System.Web.Mvc.RequireHttpsAttribute() );
Ultimately what this means is that the whole site is HTTPS. Since making those changes, the site has been running fine.
This is how you use DotnetOpenAuth with Google/OAuth2.
First, reference the DotnetOpenAuth.Ultimate package from Nuget.
Then create a provider class and the profile model class
public class GoogleClient : WebServerClient
{
private static readonly AuthorizationServerDescription GoogleDescription =
new AuthorizationServerDescription
{
TokenEndpoint = new Uri( "https://accounts.google.com/o/oauth2/token" ),
AuthorizationEndpoint = new Uri( "https://accounts.google.com/o/oauth2/auth" ),
ProtocolVersion = ProtocolVersion.V20
};
public const string ProfileEndpoint = "https://www.googleapis.com/oauth2/v1/userinfo";
public const string ProfileScope = "https://www.googleapis.com/auth/userinfo.profile";
public const string EmailScope = "https://www.googleapis.com/auth/userinfo.email";
public GoogleClient()
: base( GoogleDescription )
{
}
}
public class GoogleProfileAPI
{
public string email { get; set; }
private static DataContractJsonSerializer jsonSerializer =
new DataContractJsonSerializer( typeof( GoogleProfileAPI ) );
public static GoogleProfileAPI Deserialize( Stream jsonStream )
{
try
{
if ( jsonStream == null )
{
throw new ArgumentNullException( "jsonStream" );
}
return (GoogleProfileAPI)jsonSerializer.ReadObject( jsonStream );
}
catch ( Exception ex )
{
return new GoogleProfileAPI();
}
}
}
Then, in your login page (login controller) have this code:
private static readonly GoogleClient googleClient = new GoogleClient
{
ClientIdentifier = "client_id",
ClientCredentialApplicator = ClientCredentialApplicator.PostParameter( "client_secret" )
};
// Page_Load of login page if WebForms
// Login action of the Account controller if MVC
IAuthorizationState authorization = googleClient.ProcessUserAuthorization();
if ( authorization == null )
{
// Kick off authorization request
// Google will redirect back here
Uri uri = new Uri( "http://your.application.address/login" );
googleClient.RequestUserAuthorization( returnTo: uri,
scope: new[] { GoogleClient.ProfileScope, GoogleClient.EmailScope } );
}
else
{
// authorization. we have the token and
// we just go to profile APIs to get email (and possibly other data)
var request =
WebRequest.Create(
string.Format( "{0}?access_token={1}",
GoogleClient.ProfileEndpoint,
Uri.EscapeDataString( authorization.AccessToken ) ) );
using ( var response = request.GetResponse() )
{
using ( var responseStream = response.GetResponseStream() )
{
var profile = GoogleProfileAPI.Deserialize( responseStream );
if ( profile != null &&
!string.IsNullOrEmpty( profile.email ) )
FormsAuthentication.RedirectFromLoginPage( profile.email, false );
}
}
}
Here is the recommended way to use Google authentication as well as a few other social integrations:
http://www.asp.net/mvc/tutorials/mvc-5/create-an-aspnet-mvc-5-app-with-facebook-and-google-oauth2-and-openid-sign-on
In order to use oauth2 (assuming your using MVC)
Enable the Google OpenID provider
Open the App_Start\Startup.Auth.cs file and remove the comment characters in //app.UseGoogleAuthentication(); to enable Google authentication.
Under Use another service to log in, click Google. The user is then redirected to the google site where you will enter your credentials.
If you don't have this file or folder "app_start", then you probably created a 'blank' project, instead of an "internet" project when you first created the solution. It's much easier (if planning on using external logins) to select 'internet application' when you first begin. Not sure what editor your using, but Visual Studio 2012/2013 make this ridiculously easy!
If your going to use OpenID which is now the recommended way, here is a great starting point: https://developers.google.com/accounts/docs/OpenID#settingup
Lastly, if you have access to NUGET through your editor like (Visual studio) , you'll find these tasks, like adding oAuth-1/2 or openId have been made very easy..
Here is a last link that would get you off in the right direction if the above doesn't really fit your build... With a few more details, I would be more than happy to help guide you to the best solution. One thing I can say is that oauth2 IS still very relevant and used in many applications today, and you wouldn't be wrong implementing this while starting a new project today - it would be the right way to go (or at least one of the right ways to go)... Hope some of this helps and isn't just going down a path you have already been down.
Hope all is well.

Azure Mobile Services vs MVC4 SimpleMembership

When using an ASP.Net MVC4 site, it's very easy to add OAuth authentication with SimpleMembership.
OAuthWebSecurity.RegisterTwitterClient(consumerKey,consumerSecret);
When using Azure Mobile Services on a client device, it's very easy to add OAuth authentication.
await App.MobileService.LoginAsync(MobileServiceAuthenticationProvider.Twitter);
The problem is that these are two different data stores. I need to users to be able to register and/or login from either the app or the site. What is the best/easiest way to provide integrated OAuth authentication from devices and an ASP.Net site? Are there samples available?
I was only able to achieve this with Twitter and Facebook logins when Azure Mobile Services and MVC SimpleMembership were in play. Please see this thread which admittedly has a lot to look through, but it does explain my findings in pretty good detail.
http://social.msdn.microsoft.com/Forums/en-US/azuremobile/thread/d54d28c6-6941-4af5-b116-dc8c51820498
Sorry I couldn't give you any code, because my stated goal was to not write any authentication/security code for this integration.
Nate
I just finished posting a sample that uses ASP.NET MVC4 simple membership to authenticate to an Azure Mobile Service (via Facebook, in my example) at http://blogs.msdn.com/b/carlosfigueira/archive/2013/06/25/exposing-authenticated-data-from-azure-mobile-services-via-an-asp-net-mvc-application.aspx. The post contains a lot of details, but the idea is that if you can get the provider access token (from Facebook or Google, for example), you can format it and send to the backing mobile service. In the snippet below, the facebook token was stored in the session state, and is retrieved by a method that ensures that the user is logged in.
if (MobileService.CurrentUser == null)
{
var accessToken = Session["facebooktoken"] as string;
var token = new JObject();
token.Add("access_token", accessToken);
return MobileService.LoginAsync(MobileServiceAuthenticationProvider.Facebook, token).ContinueWith<bool>(t =>
{
if (t.Exception != null)
{
return true;
}
else
{
System.Diagnostics.Trace.WriteLine("Error logging in: " + t.Exception);
return false;
}
});
}