I am using this Link as a starting point as i am new to Asp.net MVC as such.
I have been able to get the data of the facebook users what permissions should i use to get the users Email ID and where?
dynamic me = client.Get("me");
if (response.ContainsKey("verified"))
{
facebookVerified = response["verified"];
}
else
{
facebookVerified = false;
}
db.ExternalUsers.Add(new ExternalUserInformation
{
UserId = newUser.UserId,
FullName = me.name,
Link = me.link,
Email = model.Email, // Want the Email ID from Facebook
Gender = me.gender,
Verified = facebookVerified
});
LOGIN CODE:
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Login(LoginModel model, string returnUrl)
{
if (ModelState.IsValid && WebSecurity.Login(model.UserName, model.Password, persistCookie: model.RememberMe))
{
return RedirectToLocal(returnUrl);
}
// If we got this far, something failed, redisplay form
ModelState.AddModelError("", "The user name or password provided is incorrect.");
return View(model);
}
What you are missing here is getting additional permission for getting the email address from facebook.
See the below two screenshot, second screenshot requests for additional information including email.
Basic Permission
More Permissions
To do that you need to this additional required info as "scope".
I did a little tutorial on how to login with facebook today and can be read here - Using Facebook Login with ASP.NET MVC 4. This will answer most of your queries.
For your question here is what you should do:
Create a FacebookScopedClient class (code below) and then in your AuthConfig.cs use it like this
var facebooksocialData = new Dictionary<string, object>();
facebooksocialData.Add("scope", "email, publish_stream, read_stream");
OAuthWebSecurity.RegisterClient(new FacebookScopedClient(
appId: "xxxxxxxx",
appSecret: "xxxxxxxxxxxxxxxxxxx",
scope:"email, user_likes, friends_likes, user_birthday),
"Facebook",
null
);
Code for FacebookScopedClient class -
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using DotNetOpenAuth.AspNet;
using Newtonsoft.Json;
public class FacebookScopedClient : IAuthenticationClient
{
private string appId;
private string appSecret;
private string scope;
private const string baseUrl = "https://www.facebook.com/dialog/oauth?client_id=";
public const string graphApiToken = "https://graph.facebook.com/oauth/access_token?";
public const string graphApiMe = "https://graph.facebook.com/me?";
private static string GetHTML(string URL)
{
string connectionString = URL;
try
{
System.Net.HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(connectionString);
myRequest.Credentials = CredentialCache.DefaultCredentials;
//// Get the response
WebResponse webResponse = myRequest.GetResponse();
Stream respStream = webResponse.GetResponseStream();
////
StreamReader ioStream = new StreamReader(respStream);
string pageContent = ioStream.ReadToEnd();
//// Close streams
ioStream.Close();
respStream.Close();
return pageContent;
}
catch (Exception)
{
}
return null;
}
private IDictionary<string, string> GetUserData(string accessCode, string redirectURI)
{
string token = GetHTML(graphApiToken + "client_id=" + appId + "&redirect_uri=" + HttpUtility.UrlEncode(redirectURI) + "&client_secret=" + appSecret + "&code=" + accessCode);
if (token == null || token == "")
{
return null;
}
string access_token = token.Substring(token.IndexOf("access_token="), token.IndexOf("&"));
string data = GetHTML(graphApiMe + "fields=id,name,email,username,gender,link&" + access_token);
// this dictionary must contains
Dictionary<string, string> userData = JsonConvert.DeserializeObject<Dictionary<string, string>>(data);
return userData;
}
public FacebookScopedClient(string appId, string appSecret, string scope)
{
this.appId = appId;
this.appSecret = appSecret;
this.scope = scope;
}
public string ProviderName
{
get { return "Facebook"; }
}
public void RequestAuthentication(System.Web.HttpContextBase context, Uri returnUrl)
{
string url = baseUrl + appId + "&redirect_uri=" + HttpUtility.UrlEncode(returnUrl.ToString()) + "&scope=" + scope;
context.Response.Redirect(url);
}
public AuthenticationResult VerifyAuthentication(System.Web.HttpContextBase context)
{
string code = context.Request.QueryString["code"];
string rawUrl = context.Request.Url.OriginalString;
//From this we need to remove code portion
rawUrl = Regex.Replace(rawUrl, "&code=[^&]*", "");
IDictionary<string, string> userData = GetUserData(code, rawUrl);
if (userData == null)
return new AuthenticationResult(false, ProviderName, null, null, null);
string id = userData["id"];
string username = userData["username"];
userData.Remove("id");
userData.Remove("username");
AuthenticationResult result = new AuthenticationResult(true, ProviderName, id, username, userData);
return result;
}
}
References:
Facebook web application extended permissions second step dont show second-step-dont-show/18904735#18904735
Authenticating Facebook users with MVC 4 OAuth AND obtaining Scope Permissions!
Related
I have created a simple ASP.Net web forms application and want to upload a file to One Drive. I implemented MS Graph APIs for this purpose. There are three files, Upload.aspx, Upload.aspx.cs, and MsalAuthentication.cs (The code is also given below). When I click on "Upload button" and the control goes to:
var result = await _clientApplication.AcquireTokenByUsernamePassword(_scopes, _username, _password).ExecuteAsync();, it stucks here and doesn't move to the next statement.
In web.Config file, I have also given applicationId and tenantId as:
< appSettings >
< add key="tenantId" value="some id" />
< add key="applicationId" value="some id" />
< /appSettings>
Can anybody tell me about the issue?
The code is given below
Upload.aspx.cs
using System.Web.UI;
using System.Web.UI.WebControls;
using System.IO;
using System.Security;
using Microsoft.Identity.Client;
using Microsoft.Graph;
using Microsoft.Extensions.Configuration;
using Helpers;
using System.Configuration;
using System.Collections.Specialized;
namespace WebFormsOneDrive
{
public partial class Upload : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Button1_Click(object sender, EventArgs e)
{
var config = LoadAppSettings();
if (config == null)
{
Console.WriteLine("Invalid appsettings.json file.");
return;
}
var userName = ReadUsername();
var userPassword = ReadPassword();
var client = GetAuthenticatedGraphClient(config, userName, userPassword);
// request 1 - upload small file to user's onedrive
var fileName = FileUpload1.FileName;
var filePath = Path.Combine(#"D:\webform\upload\", fileName);
FileStream fileStream = new FileStream(filePath, FileMode.Open);
var uploadedFile = client.Me.Drive.Root
.ItemWithPath(fileName)
.Content
.Request()
.PutAsync<DriveItem>(fileStream)
.Result;
Console.WriteLine("File uploaded to: " + uploadedFile.WebUrl);
}
private static NameValueCollection LoadAppSettings()
{
try
{
//var config = new ConfigurationBuilder()
// .SetBasePath(System.IO.Directory.GetCurrentDirectory())
// .AddXMLFile("Web.config", false, true)
// .Build();
var config = ConfigurationManager.GetSection("appSettings") as NameValueCollection;
if (string.IsNullOrEmpty(config["applicationId"]) ||
string.IsNullOrEmpty(config["tenantId"]))
{
return null;
}
return config;
}
catch (System.IO.FileNotFoundException)
{
return null;
}
}
private static IAuthenticationProvider CreateAuthorizationProvider(NameValueCollection config, string userName, SecureString userPassword)
{
var clientId = config["applicationId"];
var authority = $"https://login.microsoftonline.com/{config["tenantId"]}/v2.0";
List<string> scopes = new List<string>();
scopes.Add("User.Read");
scopes.Add("Files.Read");
scopes.Add("Files.ReadWrite");
var cca = PublicClientApplicationBuilder.Create(clientId)
.WithAuthority(authority)
.Build();
return MsalAuthenticationProvider.GetInstance(cca, scopes.ToArray(), userName, userPassword);
}
private static GraphServiceClient GetAuthenticatedGraphClient(NameValueCollection config, string userName, SecureString userPassword)
{
var authenticationProvider = CreateAuthorizationProvider(config, userName, userPassword);
var graphClient = new GraphServiceClient(authenticationProvider);
return graphClient;
}
private static SecureString ReadPassword()
{
//Console.WriteLine("Enter your password");
//SecureString password = new SecureString();
//while (true)
//{
// ConsoleKeyInfo c = Console.ReadKey(true);
// if (c.Key == ConsoleKey.Enter)
// {
// break;
// }
// password.AppendChar(c.KeyChar);
// Console.Write("*");
//}
//Console.WriteLine();
var password = new SecureString();
password.AppendChar('p');
password.AppendChar('a');
password.AppendChar('s');
password.AppendChar('s');
password.AppendChar('w');
password.AppendChar('o');
password.AppendChar('r');
password.AppendChar('d');
return password;
}
private static string ReadUsername()
{
//string username;
//Console.WriteLine("Enter your username");
//username = Console.ReadLine();
//return username;
string userName = "abcd#domain#onmicrosoft.com";
return userName;
}
}
}
MsalAuthentication.cs
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security;
using System.Threading.Tasks;
using Microsoft.Identity.Client;
using Microsoft.Graph;
namespace Helpers
{
public class MsalAuthenticationProvider : IAuthenticationProvider
{
private static MsalAuthenticationProvider _singleton;
private IPublicClientApplication _clientApplication;
private string[] _scopes;
private string _username;
private SecureString _password;
private string _userId;
private MsalAuthenticationProvider(IPublicClientApplication clientApplication, string[] scopes, string username, SecureString password)
{
_clientApplication = clientApplication;
_scopes = scopes;
_username = username;
_password = password;
_userId = null;
}
public static MsalAuthenticationProvider GetInstance(IPublicClientApplication clientApplication, string[] scopes, string username, SecureString password)
{
if (_singleton == null)
{
_singleton = new MsalAuthenticationProvider(clientApplication, scopes, username, password);
}
return _singleton;
}
public async Task AuthenticateRequestAsync(HttpRequestMessage request)
{
var accessToken = await GetTokenAsync();
request.Headers.Authorization = new AuthenticationHeaderValue("bearer", accessToken);
}
public async Task<string> GetTokenAsync()
{
if (!string.IsNullOrEmpty(_userId))
{
try
{
var account = await _clientApplication.GetAccountAsync(_userId);
if (account != null)
{
var silentResult = await _clientApplication.AcquireTokenSilent(_scopes, account).ExecuteAsync();
return silentResult.AccessToken;
}
}
catch (MsalUiRequiredException) { }
}
var result = await _clientApplication.AcquireTokenByUsernamePassword(_scopes, _username, _password).ExecuteAsync();
_userId = result.Account.HomeAccountId.Identifier;
return result.AccessToken;
}
I think you mixed 2 concepts:
access on behalf of a user's connection (via AAD for example)
access via the security of an application (client secret)
In general we cannot pass the password of a user in clear like that to an API, we play with tokens.
The Graph Doc for all scenarios
Add a client secret to your AAD and give all the roles base you need to your api.
If you use Credential flow, you should not use "Me" in the graph call, but something like : graph.Users["user#email.com"].Drive....
Otherwise if you realy want to use password you can do that :
IPublicClientApplication publicClientApplication = PublicClientApplicationBuilder
.Create(clientId)
.WithTenantId(tenantID)
.Build();
UsernamePasswordProvider authProvider = new UsernamePasswordProvider(publicClientApplication, scopes);
GraphServiceClient graphClient = new GraphServiceClient(authProvider);
User me = await graphClient.Me.Request()
.WithUsernamePassword(email, password)
.GetAsync();
I need to connect to an API. All examples that I could find use Tokens which I can send to each transaction I desire.
Accordingly to the supplier documentation, I couldn't find anything related to tokens.
The problem is when I connect, using curl or wp_remote_post() I don't have an 'connected' object to keep doing the transactions that I need.
Bellow is how it is done in C#. I need some directions in what objects I have to use and create the same functionality in php. Thanks
Connection Class:
public class RestService: IDisposable {
private readonly HttpClient _httpClient;
private readonly string _acumaticaBaseUrl;
public RestService(
string acumaticaBaseUrl, string userName, string password, string company, string branch, string locale) {
_acumaticaBaseUrl = acumaticaBaseUrl;
_httpClient = new HttpClient(
new HttpClientHandler {
UseCookies = true,
CookieContainer = new CookieContainer()
}) {
BaseAddress = new Uri(acumaticaBaseUrl + "/entity/Default/6.00.001/"),
DefaultRequestHeaders = {
Accept = {
MediaTypeWithQualityHeaderValue.Parse("text/json")
}
}
};
//Log in to MYOB Advanced
_httpClient.PostAsJsonAsync(
acumaticaBaseUrl + "/entity/auth/login", new {
name = userName,
password = password,
company = company,
branch = branch,
locale = locale
}).Result.EnsureSuccessStatusCode();
}
void IDisposable.Dispose() {
_httpClient.PostAsync(_acumaticaBaseUrl + "/entity/auth/logout", new ByteArrayContent(new byte[0])).Wait();
_httpClient.Dispose();
}
}
////////////////
//Data submission
public string Put(string entityName, string parameters, string entity) {
var res = _httpClient.PutAsync(_acumaticaBaseUrl + "/entity/Default/6.00.001/" + entityName + "?" + parameters, new StringContent(entity, Encoding.UTF8, "application/json")).Result.EnsureSuccessStatusCode();
return res.Content.ReadAsStringAsync().Result;
}
}
I am calling the web API methods from my client project and returning the value from response header to client:
[HttpPost]
[AllowAnonymous]
[Route("login")]
public IActionResult Login(Users user)
{
string s = _repository.Users.ValidateUser(user);
if (s == "success")
{
Users u = _repository.Users.FindByUserName(user.UserName);
int pid = u.PersonId;
string role = "";
if (u != null)
{
role = _repository.RoleManager.GetRole(u.Id);
}
Response.Headers.Add("Role", role);
return Ok(pid.ToString());
}
}
And I tried the code below for getting header value in the client application:
[HttpPost]
public IActionResult Login(Users user)
{
string pid = "";
HttpClient client = service.GetService();
HttpResponseMessage response = client.PostAsJsonAsync("api/mymethod", user).Result;
Task<string> tokenResult = response.Content.ReadAsAsync<string>();
pid = tokenResult.Result.ToString();
var headers = response.Headers;
string role = "";
if (headers.TryGetValues("Role", out IEnumerable<string> headerValues))
{
role = headerValues.ToString();
}
return RedirectToAction("Profile");
}
But it returns System.String[] .
Please show me the right way for fetching data from the response header.
I found the solution:
var headers = response.Headers;
string role = "";
if (headers.TryGetValues("Role", out IEnumerable<string> headerValues))
{
role = headerValues.FirstOrDefault();
}
Don't forget to add a reference to System.Linq.
Using StringValues:
var headers = response.Headers;
string role = "";
if (headers.TryGetValues("Role", out Microsoft.Extensions.Primitives.StringValues headerValues))
{
role = headerValues.FirstOrDefault();
}
I have a Web API with only one user, I'm trying to use the basic authentication to protect it but it always returns code 401 unauthorized.
This is my code:
Class BasicAuthenticationAttribute
using System;
using System.Threading;
using System.Security.Principal;
using System.Text;
using System.Web.Http.Controllers;
using System.Web.Http.Filters;
using System.Net;
using System.Net.Http;
public class BasicAuthenticationAttribute: AuthorizationFilterAttribute
{
public override void OnAuthorization(HttpActionContext actionContext)
{
if (actionContext.Request.Headers.Authorization == null)
{
actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
}
else
{
// Gets header parameters
string authenticationString = actionContext.Request.Headers.Authorization.Parameter;
string originalString = Encoding.UTF8.GetString(Convert.FromBase64String(authenticationString));
// Gets username and password
string usrename = originalString.Split(':')[0];
string password = originalString.Split(':')[1];
// Validate username and password
if (!CheckUser.Login(usrename, password))
{
// returns unauthorized error
actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
}
}
base.OnAuthorization(actionContext);
}
}
Class Checkuser
using System;
public class CheckUser
{
public static bool Login(string username, string password)
{
if (username == "user" && password == "mypassword")
return true;
else
return false;
}
}
The API Controller
public class adduserController : ApiController
{
[HttpGet, BasicAuthentication]
[Route("api/user/{email}")]
public string adduser(string email)
{
string country_code = "";
string username = System.Threading.Thread.CurrentPrincipal.Identity.Name;
return "Welcome";
}
This is my JQuery function:
var token = '';
var headers = {};
if (token) {
headers.Authorization = 'Basic YWhdZWQer5WhtZWRAMjAxNw==';
}
$.ajax({
type: 'GET',
url: 'http://mywebapi.com',
headers: headers
}).done(function (data) {
self.result(data);
})
I don't know what is wrong with my code!! Please help
Thank you in advance
You create an empty token, then you set your headers if that token is not empty, so you never set any headers...
var token = '';
var headers = {};
if (token) {
headers.Authorization = 'Basic YWhdZWQer5WhtZWRAMjAxNw==';
}
Try
if (!token) {
For a assignment, I was trying to send a post request with a given token(no user and password values, I just had API token), this did not work for me :
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Basic",
"converted base 64 token / api token ");
This help me to be authenticate, and solved my problem :
client.DefaultRequestHeaders.Add("Authorization", "Basic JEcYcEMyantZV095WVc3G2JtVjNZbWx1");
I'm attempting to translate some English text to Chinese using Bing Translate's API.
My code is essentially what was provided on MSDN, albeit with a few modifications.
using System;
using System.Text;
using System.Net;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Web;
using System.ServiceModel.Channels;
using System.ServiceModel;
namespace AutoTranslate2
{
public class Translator
{
private string authToken;
public Translator(string clientId, string clientSecret)
{
AdmAccessToken admToken;
AdmAuthentication admAuth = new AdmAuthentication("clientId", "client secret");
admToken = admAuth.GetAccessToken();
DateTime tokenReceived = DateTime.Now;
this.authToken = "Bearer " + admToken.access_token;
}
public string TranslateMethod(
string text,
string inputLang = "en",
string outputLang = "zh-CHS", // Chinese, simplified ('zh-CHT' is traditional Chinese)
string inputType = "text/html",
string outputType = "general")
{
// Add TranslatorService as a service reference, Address:http://api.microsofttranslator.com/V2/Soap.svc
TranslatorService.LanguageServiceClient client = new TranslatorService.LanguageServiceClient();
//Set Authorization header before sending the request
HttpRequestMessageProperty httpRequestProperty = new HttpRequestMessageProperty();
httpRequestProperty.Method = "POST";
httpRequestProperty.Headers.Add("Authorization", this.authToken);
// Creates a block within which an OperationContext object is in scope.
string translationResult;
using (OperationContextScope scope = new OperationContextScope(client.InnerChannel))
{
OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = httpRequestProperty;
//Keep appId parameter blank as we are sending access token in authorization header.
translationResult = client.Translate("", "<p>" + text + "</p>", inputLang, outputLang, inputType, outputType);
}
return translationResult;
}
}
[DataContract]
public class AdmAccessToken
{
[DataMember]
public string access_token { get; set; }
[DataMember]
public string token_type { get; set; }
[DataMember]
public string expires_in { get; set; }
[DataMember]
public string scope { get; set; }
}
public class AdmAuthentication
{
public static readonly string DatamarketAccessUri = "https://datamarket.accesscontrol.windows.net/v2/OAuth2-13";
private string clientId;
private string clientSecret;
private string request;
public AdmAuthentication(string clientId, string clientSecret)
{
this.clientId = clientId;
this.clientSecret = clientSecret;
//If clientid or client secret has special characters, encode before sending request
this.request = string.Format("grant_type=client_credentials&client_id={0}&client_secret={1}&scope=http://api.microsofttranslator.com", HttpUtility.UrlEncode(clientId), HttpUtility.UrlEncode(clientSecret));
}
public AdmAccessToken GetAccessToken()
{
return HttpPost(DatamarketAccessUri, this.request);
}
private AdmAccessToken HttpPost(string DatamarketAccessUri, string requestDetails)
{
//Prepare OAuth request
WebRequest webRequest = WebRequest.Create(DatamarketAccessUri);
webRequest.ContentType = "application/x-www-form-urlencoded";
webRequest.Method = "POST";
byte[] bytes = Encoding.ASCII.GetBytes(requestDetails);
webRequest.ContentLength = bytes.Length;
using (Stream outputStream = webRequest.GetRequestStream())
{
outputStream.Write(bytes, 0, bytes.Length);
}
WebResponse webResponse = webRequest.GetResponse();
using (webResponse)
{
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(AdmAccessToken));
//Get deserialized object from JSON stream
AdmAccessToken token = (AdmAccessToken)serializer.ReadObject(webResponse.GetResponseStream());
return token;
}
}
}
}
...and somewhere else in my code, I do...
Translator t = new Translator(client_id, secret);
string output = t.TranslateMethod(text);
However, the code always returns an exception:
Unhandled Exception: System.Net.WebException: The remote server returned an error: (400) Bad Request.
at System.Net.HttpWebRequest.GetResponse()
at AutoTranslate2.AdmAuthentication.HttpPost(String DatamarketAccessUri, String requestDetails) in C:\Users\Deflect\AutoTranslate2\AutoTranslate2\Translate.cs:line 102
at AutoTranslate2.AdmAuthentication.GetAccessToken() in C:\Users\Deflect\AutoTranslate2\AutoTranslate2\Translate.cs:line 87
at AutoTranslate2.Translator..ctor(String clientId, String clientSecret) in C:\Users\Deflect\AutoTranslate2\AutoTranslate2\Translate.cs:line 26
at AutoTranslate2.Chinese.Parse(String rawText) in C:\Users\Deflect\AutoTranslate2\AutoTranslate2\Parse.cs:line 68
at AutoTranslate2.Program.Main(String[] args) in C:\Users\Deflect\AutoTranslate2\AutoTranslate2\Program.cs:line 19
I'll be the first to admit I really don't know what my code is doing, since I mostly copied and pasted from MSDN -- does anybody know why my code is returning an exception, and how I can get it to work?
It was this line:
AdmAuthentication admAuth = new AdmAuthentication("clientId", "client secret");
I forgot to swap the strings in the examples with the actual variables.