SteamAuth var from startup.auth to the view ASP.NET - asp.net-mvc

I want to get the profile information from steam. so first I've fixed that I can login through steam, I used this tutorial: http://www.oauthforaspnet.com/providers/steam/
But now I want to get the steam profile id from the user that logged in so I can use the JSON from the steam API to get the information from the user.
https://steamcommunity.com/profiles/(this id)
I hope someone can help me, I've searched for hours now, and don't have any result.
var options = new SteamAuthenticationOptions {
ApplicationKey = "Your API Key",
Provider = new OpenIDAuthenticationProvider // Steam is based on OpenID
{
OnAuthenticated = async context =>
{
// Retrieve the user's identity with info like username and steam id in Claims property
var identity = context.Identity;
}
}}; app.UseSteamAuthentication(options);

A while ago we discovered the answer:
1.) insert your key from the tutorial here:
var options = new SteamAuthenticationOptions
{
ApplicationKey = "Your API Key",
Provider = new OpenIDAuthenticationProvider // Steam is based on OpenID
{
OnAuthenticated = async context =>
{
// Retrieve the user's identity with info like username and steam id in Claims property
var identity = context.Identity;
}
}
};
app.UseSteamAuthentication(options);
2.) We discovered that steam is saving a users steam id in the database table called: 'AspNetUserLogins', the providerkey inside that table is an url made out of more pieces. For example:
http://steamcommunity.com/openid/id/here-users-steamid
We only need the users steamid, so we going to split that in step 3.
3.) Make a controller, for example: SteamController. Here we going to add a public string:
public string GetSteamID()
{
var manager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new Steam.Models.ApplicationDbContext()));
var CurrentUser = manager.FindById(User.Identity.GetUserId());
if (User.Identity.Name != "")
{
string url = CurrentUser.Logins.First().ProviderKey;
ViewBag.steamid = url.Split('/')[5]; //here we going to split the providerkey so we get the right part
}
else
{
ViewBag.steamid = "";
}
return ViewBag.steamid;
}
) now we can add some stuff, lets say we going to add profile information. Go to your SteamController and add:
[HttpGet]
public ContentResult GetProfile()
{
string url = string.Format("http://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002/?key=addyourkeyhere&steamids={0}", this.GetSteamID());
string result = null;
using (var client = new WebClient())
{
result = client.DownloadString(url);
}
return Content(result, "application/json");
}
notice that you have to add your steam key from step 1 in the url.
) make a script called: profile.js. Here we going to add our profile information.
function profilepic() {
$.ajax({
url: 'http://localhost:3365/steam/GetProfile',
dataType: 'json',
success: function (data) {
$.each(data.response.players, function (key, value) {
if ($('.profile')) {
$('.profile').append("<img src='" + value.avatar + "'> <span>" + value.personaname + "</span>")
}
if ($('.profile1')) {
$('.profile1').append("<img src='" + value.avatarfull + "'>")
}
if ($('.username')) {
$('.username').append(value.personaname)
}
console.log(value)
});
}, error: function (httpReq, status, exception) {
console.log(status + " " + exception);
}
});
}
6.) Now we have to do the final step, create a view with the classes, for example:
<div class="userprofile">
<span class="profile1"></span>
<div class="userdescription">
<h2 class="username"></h2>
</div>
</div>
) I hope this will help some people, for more questions, feel free to ask!

Related

Adding invited (guest) user to teams seems to not work properly

Hi (ref issue)
After setting up the tenant to allow invitation of user from another domain, we are able to invite external users (in set domain) to teams. This works fine when doing it manually, in the GUI.
However, when trying to add an invited user threw the windows graph API, something is not working properly.
Our procedure to invite a user to a team is as follows:
Note we are using application privileges
Invite the user to the tenant (with or without welcome mail)
https://learn.microsoft.com/en-us/graph/api/invitation-post?view=graph-rest-1.0
Add the invited user to the team
https://learn.microsoft.com/en-us/graph/api/group-post-members?view=graph-rest-1.0
Both these calls complete successfully and does not return any error messages. In all the admin GUI’s (AAD, Teams, Exchange) the user is invited and is added to the group.
But the user in question does not receive a welcome mail that he/she has been added to the team. And if the user (given we send a welcome mail in step 1) tries to access http://teams.microsoft.com the user gets notified that he/she does not have permissions and/or does not see the team.
Any tips?
API Permissions
EDIT:
After some investigation, by monitoring the network traffic. It's seems that the missing call, to get properly invited to the team is:
POST https://api.teams.skype.com/emea/beta/teams/($teamurl)/bulkUpdateRoledMembers?allowBotsInChannel=true
where you send in a list of userid (8:orgid:{userid}) and the groupid. (teamurl seems to be the channel id)
{"users":[{"mri":"8:orgid:00000000-5946-0000-87d2-b16b6fdf7a72","role":2}],"groupId":"00000000-2e8b-4d18-0000-394c6a4846d0"}
I have tried to call this from application & delegation, but get 'Unauthorized'. Also I could not find any API permission that granted access to 'api.teams.skype.com'.
I finally figured out how to get an access token to invoke bulkUpdateRoledMembers. It only works if I request an access token for it directly, so no Application Permissions and no On-Behalf-Of Flow.
private static async Task<string> GetAccessTokenForTeams(string tenantId)
{
var client = new PublicClientApplication(
clientId: "d3590ed6-52b3-4102-aeff-aad2292ab01c",
authority: $"https://login.microsoftonline.com/{tenantId}/",
userTokenCache: null);
try
{
var result = await client.AcquireTokenInteractive(new[] { "https://api.spaces.skype.com/user_impersonation" }, null).ExecuteAsync();
return result.AccessToken;
}
catch (Exception e)
{
Debug.WriteLine(e);
throw;
}
}
It turns out you also need a Skypetoken, which you can get very easily with the just acquired access token.
private static async Task<string> GetSkypeToken(string accessToken)
{
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add(HttpRequestHeader.Authorization.ToString(), "Bearer " + accessToken);
using (var response = await client.PostAsync("https://api.teams.skype.com/beta/auth/skypetoken", null))
{
var contentString = await response.Content.ReadAsStringAsync();
if (response.IsSuccessStatusCode)
{
var skypeTokenResponse = JsonConvert.DeserializeObject<SkypeTokenResponse>(contentString);
return skypeTokenResponse.Tokens.SkypeToken;
}
else
{
throw new Exception(response.StatusCode.ToString() + ": " + contentString);
}
}
}
}
private class SkypeTokenResponse
{
public Token Tokens { get; set; }
public class Token
{
public string SkypeToken { get; set; }
public string ExpiresIn { get; set; }
}
}
Then you can finally invoke bulkUpdateRoledMembers by passing both tokens along.
private static async Task<object> bulkUpdateRoledMembers(string accessToken, string skypeToken, string teamUrl, string groupId, string userId)
{
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add(HttpRequestHeader.Authorization.ToString(), "Bearer " + accessToken);
client.DefaultRequestHeaders.Add("X-Skypetoken", skypeToken);
var bodyString = JsonConvert.SerializeObject(new
{
users = new List<object>
{
new
{
mri = "8:orgid:" + userId,
role = 2
}
},
groupId = groupId
});
var body = new StringContent(bodyString, Encoding.UTF8, "application/json");
using (var response = await client.PutAsync($"https://teams.microsoft.com/api/mt/emea/beta/teams/{teamUrl}/bulkUpdateRoledMembers?allowBotsInChannel=true", body))
{
var contentString = await response.Content.ReadAsStringAsync();
if (response.IsSuccessStatusCode)
{
var jsonresult = JObject.Parse(contentString);
return jsonresult;
}
else
{
throw new Exception(response.StatusCode.ToString() + ": " + contentString);
}
}
}
}

How to Post to facebook using graph api in ASP.Net Core 2.0?

I already have authenticated users in OAuth. I have my app-id, my access token which I extended. Facebook recently updated their Graph Api to v3.1. I have searched all over the net but no luck. How can i get the post in my Create-Post controller to save both to my database and post to facebook as well. Posting as a page or post to user wall examples would be great, in ASP.NET Core MVC Please.
I have tried everything on the web but nothing works. I have removed the edits on my post controller so it can only store the user-post to my database for now. Please help, how can I tackle this problem good people.
//post create post
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(Post post)
{
string url = "http://graph.facebook.com/v3.1/";
string myAppID = "my_app_id";
string myAccessToken = "my_access_token";
if (ModelState.IsValid)
{
_db.Add(post);
await _db.SaveChangesAsync();
return RedirectToAction(nameof(Index), new { userId = post.UserId });
}
return View(post);
Good-day fellow developers. In case any of you out there are still experiencing problems posting to Facebook from your .NET Core 2.0 applications here is the solution.
First of all, the documentation from Facebook is very misleading(for myself it was). It turns out that the actual access token you need is the Page Access Token. You do not need app access token/user access token when doing queries to the API all you need is the page access token. This of-course works only if you are the Application and page admin no need for App Review at this point. I hope you figure out how to extend this access token to never expire here
public class FacebookController : Controller
{
readonly string _accessToken;
readonly string _pageID;
readonly string _facebookAPI = "https://graph.facebook.com/";
readonly string _pageEdgeFeed = "feed";
public FacebookController(string accessToken, string pageID)
{
_accessToken = accessToken;
_pageID = pageID;
_postToPageURL = $"{_facebookAPI}{pageID}/{_pageEdgeFeed}";
}
// Publish a simple text post
public async Task<Tuple<int,string>> PublishPost(string postText)
{
using (var http = new HttpClient())
{
var postData = new Dictionary<string, string>
{
{"access_token", _accessToken },
{"message", postText }
};
var httpResponse = await http.PostAsync(
_postToPageURL,
new FormUrlEncodedContent(postData));
var httpContent = await httpResponse.Content.ReadAsStringAsync();
return new Tuple<int, string>(
(int)httpResponse.StatusCode,
httpContent
);
}
}
This is how you use it on your controller:
//declare your strings, I stored them in a class
public static class FacebookSettings
{
public static string pageID = "Your-Page-Id";
public static string Access_Token = "Your-Page-Access-Token";
}
//post create post
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(Post post)
{
if (ModelState.IsValid)
{
//here you pass in your parameters
var facebook = new
FacebookController
(
FacebookSettings.Access_Token,
FacebookSettings.pageID
);
var simpleText = Task.Run(async () =>
{
using (var http = new HttpClient())
{
return await facebook.PublishSimplePost(post.UserPost);
}
});
//Debug your application to check if you get the correct id here:
var simpleTextJson = JObject.Parse(simpleText.Result.Item2);
_db.Add(post);
await _db.SaveChangesAsync();
return RedirectToAction(nameof(Index), new { userId = post.UserId });
}
return View(post);
I also had the same problem after my website was not approved to publish_pages on Facebook.
I would recommend that you try using a javascript SDK to do that, it helped me while I was facing difficulties with .NET-core. This link might help you:
https://developers.facebook.com/docs/javascript/quickstart
<script>
window.fbAsyncInit = function() {
FB.init({
appId : 'your-app-id',
autoLogAppEvents : true,
xfbml : true,
version : 'v3.1'
});
};
(function(d, s, id){
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) {return;}
js = d.createElement(s); js.id = id;
js.src = "https://connect.facebook.net/en_US/sdk.js";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));
</script>
This will be just for loading of the SDK, you will still need a getInfo function and a post function. This how I did it, try it and see how it goes. All the best.
<script>
var access;
function getInfo(){
FB.api('/me','GET',{fields: 'id,name,email'},
function(response){
document.getElementById('status').innerHTML = response.email;
access = document.getElementById('mapping').innerHTML = response.id;
return access;
});
}
function post(){
var x = { message : document.getElementById('textinput').value,
access_token : access};
FB.api('/me/feed','POST',x,
function(response){
document.getElementById('testing').innerHTML = x.message;
});
}
</script>

Authentication refused to display Inside iframe with MVC app

I have created an MVC application and in the Home page, I have a Power BI Dashboard Report, so I have configured the Power BI and Azure AD configuration in Index action, once Index action is called, it will verify the Authentication and Redirect to Redirect Action Method. In the method, Authentication has been verified and calls the Power BI action method and shows the report.
The report is working fine in the page, but when set it to Iframe, it is not working and shows the below error.
Home Page Index Action:
public ActionResult Index()
{
var #params = new NameValueCollection
{
//Azure AD will return an authorization code.
//See the Redirect class to see how "code" is used to AcquireTokenByAuthorizationCode
{"response_type", "code"},
//Client ID is used by the application to identify themselves to the users that they are requesting permissions from.
//You get the client id when you register your Azure app.
{"resource", "https://analysis.windows.net/powerbi/api"},
{"redirect_uri", "xxxx/home/Redirect."}
};
//Create sign-in query string
var queryString = HttpUtility.ParseQueryString(string.Empty);
queryString.Add(#params);
string authorityUri = "https://login.windows.net/common/oauth2/authorize/";
var authUri = String.Format("{0}?{1}", authorityUri, queryString);
ViewBag.authUri = authUri;
return View();
}
Redirect Action Method:
public async Task<ActionResult> Redirect()
{
string code = Request.Params["code"];
if (code != null)
{
AuthenticationContext AC = new AuthenticationContext("https://login.windows.net/common/oauth2/authorize", TC);
ClientCredential cc = new ClientCredential("xxxxx", "xxxxxxx");
AuthenticationResult AR = await AC.AcquireTokenByAuthorizationCodeAsync(code, new Uri("http://localhost:43333/home/redirect"), cc);
//Set Session "authResult" index string to the AuthenticationResult
Session["authResult"] = AR;
} else {
//Remove Session "authResult"
Session["authResult"] = null;
}
return RedirectToAction("POWERBI", "Home");
}
Power BI action:
public async Task<ActionResult> POWERBI()
{
AuthenticationResult authResult;
authResult = (AuthenticationResult)Session["authResult"];
var token = authResult.AccessToken;
ViewBag.Token = token;
var tokenCredentials = new TokenCredentials(token, "Bearer");
// Create a Power BI Client object. It will be used to call Power BI APIs.
using (var client = new PowerBIClient(new Uri(ApiUrl), tokenCredentials))
{
// Get a list of dashboards.
var dashboards = await client.Dashboards.GetDashboardsInGroupAsync(GroupId);
// Get the first report in the group.
var dashboard = dashboards.Value.FirstOrDefault();
//var dashboard = dashboards.Value.Where(w => w.Id == "DashboardId");
if (dashboard == null)
{
return View(new EmbedConfig()
{
ErrorMessage = ""
});
}
// Generate Embed Token.
var generateTokenRequestParameters = new GenerateTokenRequest(accessLevel: "view");
var tokenResponse = await client.Dashboards.GenerateTokenInGroupAsync(GroupId, dashboard.Id, generateTokenRequestParameters);
if (tokenResponse == null)
{
return View(new EmbedConfig()
{
ErrorMessage = "."
});
}
// Generate Embed Configuration.
var embedConfig = new EmbedConfig()
{
EmbedToken = tokenResponse,
EmbedUrl = dashboard.EmbedUrl,
Id = dashboard.Id
};
return View(embedConfig);
}
}
In home page view inside iframe:
<iframe src="#Url.Action("Index", "Home")" class="col-lg-12 col-md-12 col-sm-12" height="450"> </iframe>
NOTE :
- Feature is working fine without Iframe.
- problem while show the report in Iframe.
Error:
Refused to display url in a Iframe because it sets X-frame-options-to deny
The error message means the <iframe src> you are trying to pull into your site doesn't allow it to be hosted within a iframe. It is sending down the response header:
X-Frame-Options: DENY
And the browser is blocking the framing. The host page is doing this to prevent cross-frame scripting attacks.

How to pass user input from view to a class in MVC

I imagine this must be pretty basic, but all my search results only show how to pass data the other way ( model to controller, controller to view, and then view back to controller, but nothing from controller back to model(class). I am trying to pass user input for a search parameter into the query string for an API. In the view:
<form method="post" action="~/Models/Search">
<input name="artist" placeholder="Enter artist's name" />
#{Search temp = new Search();
if (Request.Form["artist"] != null) //this method doesn't work; trying to get user response and pass it back to search class;
{ temp.Artist = Request.Form["artist"].ToLower(); } //have to hardcode search parameter at this time
}
<!--<button>Click Me</button>-->
<script>
var weather = Object();
$(document).ready(function () {
$('button').click(function () {
// var artist = $("#artist").val();
$.get("#Url.Action("SearchArtist", "Home")", function (response) {
console.log(response);
artistInfo = ko.mapping.fromJS(response); //populate the artist search object
ko.applyBindings(artistInfo);
});
});
});
The class:
public class Search
{
string artist;
public string Artist { get; set;}
public Object getArtistInfo()
{
string appID = "*************** ";
artist = "metallica";
string url = "http://developer.echonest.com/api/v4/artist/search?api_key="+ appID + "&format=json&name=" + artist + "&results=1&bucket=genre&bucket=songs";
//synchronous client;
var client = new WebClient();
var content = client.DownloadString(url);
var serializer = new JavaScriptSerializer();
var jsonContent = serializer.Deserialize<Object>(content);
return jsonContent;
}
}
The controller:
public ActionResult ArtistInfo()
{
return View();
}
public JsonResult SearchArtist()
{
Search artist = new Search();
return Json(artist.getArtistInfo(), JsonRequestBehavior.AllowGet);
}
Try to add attributes (runat="server" and id="chooseyourid") to html forms results below :
if you want to access to values in your code behinde you just need to write the id of your element like below :
/artiste.value;/

How to show MVC logged in username with AngularJs

I am using MVC 5 / WebApi 2 and AngularJs. I want to display the Logged in username in my view. I know how to display that information using razor but how can I do it with Angular? So basically I need to do this with Angular.
<span >Logged In As: #Html.ActionLink(User.Identity.GetUserName(), "Manage", "Account", routeValues: null, htmlAttributes: new { title = "Manage", #style = "color:white;float:right" })</span>
apiUserController
public class apiUserController : ApiController
{
// GET api/<controller>
public List<ApplicationUser> Get()
{
using (var context = new ApplicationDbContext())
{
List<ApplicationUser> users = new List<ApplicationUser>();
users = context.ApplicationUsers
.ToList();
return users;
}
}
}
Updated
public IHttpActionResult Get()
{
using (var context = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext())))
{
var user = context.FindById(User.Identity.GetUserId());
var loggedInUser = user.UserName;
return Ok(loggedInUser);
}
}
you'll need to create a service that returns your user information
angular.module('app').factory('Authentication', function ($resource) {
var resource = $resource('/user', {}, {
query: {
method: 'GET',
cache: true
}
});
return resource.get().$promise;
});
* note that you'll need to create and endpoint that will send you the user data as json using web api
once you got it done you'll be able to use it in any controller (let's assume you have a homecontroller, it could be a headercontroller or any other)
angular.module('app').controller('HomeController', ['$scope', 'Authentication', function ($scope, Authentication) {
$scope.authentication = Authentication;
}]);
then use it in your view like:
<span >Logged In As: {{authentication.user.username}} </span>
EDIT:
your api controller as you suggested could be like
public HttpResponseMessage Get()
{
var userId = getCurrentUserId(); //something like that
using (var context = new ApplicationDbContext())
{
ApplicationUser user = new ApplicationUser();
user = context.ApplicationUsers.SingleOrDefault(x=>x.id==userId);
return user;
}
}
try to read http://www.asp.net/web-api/overview/formats-and-model-binding/json-and-xml-serialization
for routing try to read this article (I guess you are using web api 2)
http://www.asp.net/web-api/overview/web-api-routing-and-actions/attribute-routing-in-web-api-2
If you want to cheat a little, you can do this in <head> in your _Layout:
<script type="text/javascript">
(function(myApp) {
myApp.username = "#User.Identity.GetUserName()";
//optional
myApp.otherStuff = "#moreMvcStuff";
})(window.myApp = window.myApp || {});
</script>
Then start your angular app like this:
(function (myApp) {
"use strict";
//var app = set up your angular app
app.run(["$rootScope",
function ($rootScope) {
$rootScope.appSettings = {
username: myApp.username
};
}
]);
})(window.myApp = window.myApp || {});
What you are doing is creating a single value on the window called myApp (or name it whatever you like) and passing it into your IIFE. This gives you access to it inside your angular script, bot only in that on block. So if you want it to stick around, you need to put it in a service or your rootScope.
In the app.run block, you can stick it in your rootScope or wherever you want it.
Now in your views you can display it with {{appSettings.username}}.
I call this "cheating" because it's specifically for MVC or webforms and it's not the "angular way". If you ever migrated to a fully agnostic html/js client (no asp.net mvc) and web APIs, you'd need to do what is in the currently-accepted answer.

Resources