what it means to host a web player unity3d file on server like dropbox loading it into facebook canvas and use backend server like GameSparks - host

I'm new to backend servers and hosting files so if you could give me a starting point just to undersand how it works.
If I can log in with a facebook profile somehow this data saved in the dropbox and if I try to log in again with a different profile I face this
"The current user has a Facebook profile and it’s not the profile they have just tried to log in with" this from the GameSparks documentation which turns into error <"accessToken":"ACCOUNT_ALREADY_LINKED">recieved from GameSparks

Solved
after 12 hours I discovered that u have to disconnect from the server and reconnect
forexample when you want to link a facebook profile the server is now connected to that user so when you want to link another profile u have to disconnect from the previous profile and connect then wait till the server is available then you could link the new profile
using GameSparks.Api.Requests;
using GameSparks.Api.Messages;
using GameSparks.Api.Responses;
using GameSparks.Core;
public void Awake()
{
FB.Canvas.SetAspectRatio(9,16,FBScreen.CenterHorizontal());
if (!FB.IsInitialized)
{
FB.Init(FacebookLogin);
}
else
{
FacebookLogin();
}
}
public void FacebookLogin()
{
if (!FB.IsLoggedIn)
{
FB.Login("email", GameSparksLogin);
}
}
public void GameSparksLogin(FBResult result)
{
StartCoroutine (GameSparksLoginProcess ());
}
IEnumerator GameSparksLoginProcess(){
GS.Reset ();
float i = 0;
while (true) {
if(!(GS.Available)){
i += 0.2f;
yield return new WaitForSeconds(0.2f);
}else{
Debug.Log("wait: "+i+" seconds");
break;
}
}
if (FB.IsLoggedIn)
{
new FacebookConnectRequest().SetAccessToken(FB.AccessToken).SetDoNotLinkToCurrentPlayer(false)
.Send((response) =>
{
if (response.HasErrors)
{
Debug.Log("Something failed when connectiong with Facebook");
}
else
{
Debug.Log("GameSparks Facebook Login Successful");
}
});
}
}

Related

.NET Core 3.1 web application with React - how to prevent access based on Active Directory group

I have a .NET Core 3.1 web application with React using windows authentication.
When a user enters their Active Directory credentials i would like to verify they belong to a particular Active Directory group before allowing access to the React app.
I have tried setting the default endpoint to a Login Controller to verify the user's groups but i don't know how to redirect to the React app if they do have the valid group.
Startup.cs:
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller}/{action=Index}/{id?}",
defaults: new { Controller = "Login", action = "Index" });
});
LoginController:
public IActionResult Index()
{
if (HttpContext.User.Identity.IsAuthenticated)
{
string[] domainAndUserName = HttpContext.User.Identity.Name.Split('\\');
//AuthenticateUser verifies if the user is in the correct Active Directory group
if (AuthenticateUser(domainAndUserName[0], domainAndUserName[1]))
{
//This is where i would like to redirect to the React app
return Ok(); //This does not go to the react app
return LocalRedirect("http://localhost:50296/"); //This will keep coming back to this method
}
return BadRequest();
}
}
Is it possible to redirect to the React app from the controller?
Is there a better way to verify an active directory group, possibly through authorizationService.js?
I've been in this situation before, and solved it with custom implementation of IClaimsTransformation. This approach may also be used with OpenId Connect and other authentication systems that requires additional authorization.
With this approach, you can use authorize attribute on controller that serves your React app
[Authorize(Roles = "HasAccessToThisApp")]
and
User.IsInRole("HasAccessToThisApp")
elsewhere in code.
Implementation. Please note that TransformAsync will be called on every request, some caching is recommended if any time-consuming calls.
public class YourClaimsTransformer : IClaimsTransformation
{
private readonly IMemoryCache _cache;
public YourClaimsTransformer(IMemoryCache cache)
{
_cache = cache;
}
public Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal incomingPrincipal)
{
if (!incomingPrincipal.Identity.IsAuthenticated)
{
return Task.FromResult(incomingPrincipal);
}
var principal = new ClaimsPrincipal();
if (!string.IsNullOrEmpty(incomingPrincipal.Identity.Name)
&& _cache.TryGetValue(incomingPrincipal.Identity.Name, out ClaimsIdentity claimsIdentity))
{
principal.AddIdentity(claimsIdentity);
return Task.FromResult(principal);
}
// verifies that the user is in the correct Active Directory group
var domainAndUserName = incomingPrincipal.Identity.Name?.Split('\\');
if (!(domainAndUserName?.Length > 1 && AuthenticateUser(domainAndUserName[0], domainAndUserName[1])))
{
return Task.FromResult(incomingPrincipal);
}
var newClaimsIdentity = new ClaimsIdentity(
new[]
{
new Claim(ClaimTypes.Role, "HasAccessToThisApp", ClaimValueTypes.String)
// copy other claims from incoming if required
}, "Windows");
_cache.Set(incomingPrincipal.Identity.Name, newClaimsIdentity,
DateTime.Now.AddHours(1));
principal.AddIdentity(newClaimsIdentity);
return Task.FromResult(principal);
}
}
In Startup#ConfigureServices
services.AddSingleton<IClaimsTransformation, YourClaimsTransformer>();

Microsoft Botframework V4 Virtual Assistant Azure AD Authentication

I have downloaded, configured and deployed the Microsoft Virtual Assistant open source project from GitHub here: https://github.com/Microsoft/AI
I want to start with the calendar skill and have configured everything.
When I request my current calendar entries, the authentication prompt is shown in the botframework emulator and I am able to authenticate with my Azure AD Account.
After that, there is silence...
In SummaryDialog.cs in the CalendarSkill there is a definition for a WaterfallStep like this:
var showSummary = new WaterfallStep[]
{
GetAuthToken,
AfterGetAuthToken,
ShowEventsSummary,
CallReadEventDialog,
AskForShowOverview,
AfterAskForShowOverview
};
The step GetAuthToken is executed, but then execution stops. AfterGetAuthToken is not called at all.
This is the GetAuthToken function inside the project:
protected async Task<DialogTurnResult> GetAuthToken(WaterfallStepContext sc, CancellationToken cancellationToken)
{
try
{
var skillOptions = (CalendarSkillDialogOptions)sc.Options;
// If in Skill mode we ask the calling Bot for the token
if (skillOptions != null && skillOptions.SkillMode)
{
// We trigger a Token Request from the Parent Bot by sending a "TokenRequest" event back and then waiting for a "TokenResponse"
// TODO Error handling - if we get a new activity that isn't an event
var response = sc.Context.Activity.CreateReply();
response.Type = ActivityTypes.Event;
response.Name = "tokens/request";
// Send the tokens/request Event
await sc.Context.SendActivityAsync(response);
// Wait for the tokens/response event
return await sc.PromptAsync(SkillModeAuth, new PromptOptions());
}
else
{
return await sc.PromptAsync(nameof(MultiProviderAuthDialog), new PromptOptions());
}
}
catch (SkillException ex)
{
await HandleDialogExceptions(sc, ex);
return new DialogTurnResult(DialogTurnStatus.Cancelled, CommonUtil.DialogTurnResultCancelAllDialogs);
}
catch (Exception ex)
{
await HandleDialogExceptions(sc, ex);
return new DialogTurnResult(DialogTurnStatus.Cancelled, CommonUtil.DialogTurnResultCancelAllDialogs);
}
}
Am I doing anything wrong in the code or is there anything missing in my configuration?
I found out, if ngrok is not on the PC and configured, the virtual Assistatn does not work.

SignalR doesn't push message to client

I am implementing functionality to notify the user of long running job completions using SignalR in an AngularJS application.I have created groups of user based on their name,so for each user a group of his name and different connectionids which he has opened up will be created and he would be notified by his group. I want to notify the user on two pages i.e. landing Page and Job Run Page as even if the user is on landing page and job run completes he should be notified of it.
For the same reason i am creating group by his name on both the pages,so that if he is on any page he would be nofied through the group.
On landing page controller js file i have written code to add the user in group as follow...
$rootScope.signalRHub = $.connection.signalRHub;
$rootScope.hubStart = null;
$rootScope.startHub = function () {
if ($rootScope.hubStart == null)
{
$rootScope.hubStart = $.connection.hub.start();
}
return $rootScope.hubStart;
}
$scope.$on('$locationChangeStart', function (event) {
if ($rootScope.userName != "") {
$rootScope.signalRHub.server.leaveGroup($rootScope.userName);
}
});
// Start the connection
$rootScope.startHub().done(function () {
$rootScope.signalRHub.server.joinGroup($rootScope.userName);
});
on Job Run controller js file i have written following code....
$rootScope.signalRHub.client.showNotification = function (message) {
notify('Your notification message');//notify is the angular js directive injected in this controller which runs fine
};
$scope.$on('$locationChangeStart', function (event) {
$rootScope.signalRHub.server.leaveGroup($rootScope.studyid);
});
// Start the connection
$rootScope.startHub().done(function () {
$rootScope.signalRHub.server.joinGroup($rootScope.userName
});
My Hub File.....
[EnableCors(origins: "*", headers: "*", methods: "*")]
public class SignalRHub : Hub
{
public Task JoinGroup(string groupName)
{
return Groups.Add(Context.ConnectionId, groupName);
}
public Task LeaveGroup(string groupName)
{
return Groups.Remove(Context.ConnectionId, groupName);
}
public void ShowNotification(string jobRunDetailId, string userName)
{
if (!string.IsNullOrEmpty(userName))
{
var context = GlobalHost.ConnectionManager.GetHubContext<SignalRHub>();
context.Clients.Group(userName).showNotification(jobRunDetailId);
}
}
}
The issue is when i run the application the group add functionality for both pages works fine.but when i call "showNotification" from Hub it doesn't show any message.
But strange thing is if i comment the "$rootScope.startHub().done...." function on landing page then the jobrun page notify functionality works fine.I am not sure if writing "$rootScope.startHub().done()..." on two places is creating this problem.please help.
You need to wire up all callbacks before calling start. If you turn client side logging on, it'll tell you what hubs you are subscribed to.
Aside:
[EnableCors] is a webapi specific attribute that does not work in SignalR.

Error 404 when calling Google Cloud Endpoint API from Google Apps Script

I am trying to call a Google Cloud Endpoint API (developed on App Engine) via Google Apps Script. The endpoint is up and running, honestly I don't know which URL I should use but through Google Chrome Web Tools it looks like the URL is something like:
https://myapp.appspot.com/_ah/api/myendpointapi/v1/myEndPointMethod/
Along with API parameters directly included in the URL, separeted by slashes:
https://myapp.appspot.com/_ah/api/myendpointapi/v1/myEndPointMethod/param1value/param2value/...
Now, in order to call that API from Google App Script I am using the following code snippet:
function myFunction() {
var params =
{
"param1" : "param1value",
"param2" : "param2value",
};
var result = UrlFetchApp.fetch('https://myapp.appspot.com/_ah/api/myendpointapi/v1/myEndPointMethod/', params);
DocumentApp.getUi().alert(result);
}
However I always get a 404 error. If I have to be honest I don't even know if UrlFetchApp is the correct way of calling the API. I noticed this thread on StackOverflow but no one answered. What's the correct URL to use? Many thanks.
EDIT: Now I am trying with an API method which does not require any parameter. I found a way to call a specific URL (using method='get' as suggested by the answer below) but now I get a 401 error because it says I am not logged in. I believe I need to use some kind of OAuth parameter now. Any idea? I tryed using OAuthConfig but no luck with that as well :( From App Engine logs I can see the following error:
com.google.api.server.spi.auth.GoogleIdTokenUtils verifyToken: verifyToken: null
com.google.api.server.spi.auth.AppEngineAuthUtils getIdTokenEmail:
getCurrentUser: idToken=null
function myFunction() {
var result = UrlFetchApp.fetch('myurl', googleOAuth_());
result = result.getContentText();
}
function googleOAuth_() {
var SCOPE = 'https://www.googleapis.com/auth/drive';
var NAME = 'myAPIName';
var oAuthConfig = UrlFetchApp.addOAuthService(NAME);
oAuthConfig.setRequestTokenUrl('https://www.google.com/accounts/OAuthGetRequestToken?scope='+SCOPE);
oAuthConfig.setAuthorizationUrl('https://www.google.com/accounts/OAuthAuthorizeToken');
oAuthConfig.setAccessTokenUrl('https://www.google.com/accounts/OAuthGetAccessToken');
oAuthConfig.setConsumerKey('anonymous');
oAuthConfig.setConsumerSecret('anonymous');
return {oAuthServiceName:NAME, oAuthUseToken:'always'};
}
UrlFetchApp is the only way to call a Google Cloud Endpoints API at the moment. The second parameter to UrlFetchApp.fetch is a special key-value map of advanced options. To pass POST parameters, you need to do the following:
UrlFetchApp.fetch(url, {
method: 'post',
payload: {
"param1" : "param1value",
"param2" : "param2value",
}
});
I was fighting a similar (not the same) problem, when testing feasibility of a GCM backed by EndPoints server. Basically testing if it is possible to get the Google Spreadsheet Appscript to send notification to an Android device. Please bear with me, the following explanation may be a bit convoluted;
Starting with a standard 'Cloud Messaging for Android', backed by the 'App Engine Backend with Google Cloud Messaging', I managed to build a test system that would send messages between Android devices (Github here).
Here is a VERY sparse EndPoints server code that handles register / un-register Android devices, as well as reporting registered devices and sending a message to a list of registered devices.
WARNING: This is not a production quality code, it is stripped of any logging, error handling in order to keep it short.
#Api( name = "gcmEP", version = "v1",
namespace = #ApiNamespace(ownerDomain = "epgcm.example.com", ownerName = "epgcm.example.com", packagePath = "" )
)
public class GcmEP {
#ApiMethod(name = "registToken")
public void registToken(#Named("token") String token) {
if (ofy().load().type(TokenRec.class).filter("token", token).first().now() == null) {
ofy().save().entity(new TokenRec(token)).now();
}
}
#ApiMethod(name = "unregToken")
public void unregToken(#Named("token") String token) {
TokenRec record = ofy().load().type(TokenRec.class).filter("token", token).first().now();
if (record != null) {
ofy().delete().entity(record).now();
}
}
#ApiMethod(name = "listTokens")
public CollectionResponse<TokenRec> listTokens() {
return CollectionResponse.<TokenRec>builder().setItems(ofy().load().type(TokenRec.class).list()).build();
}
#ApiMethod(name = "sendMsg")
public void sendMsg(#Named("message") String message) throws IOException {
if (message != null && message.length() > 0) {
Sender sender = new Sender(System.getProperty("gcm.api.key"));
Message msg = new Message.Builder().addData("message", message).build();
for (TokenRec record : ofy().load().type(TokenRec.class).list()) {
Result result = sender.send(msg, record.getToken(), 4);
if (result.getMessageId() != null) {
// handle CanonicalRegistrationId
} else {
// handle errors, delete record
}
}
}
}
}
Android code for registration and message sending is shown here, even if it is not relevant.
GcmEP mRegSvc;
String mToken;
// register device on EndPoints backend server
private void registerMe() {
new Thread(new RegisterMe(this)).start();
}
private class RegisterMe implements Runnable {
Activity mAct;
public RegisterMe(Activity act) { mAct = act; }
public void run() {
String senderId = null;
if (mAct != null) try {
if (mRegSvc == null) {
mRegSvc = new GcmEP
.Builder(AndroidHttp.newCompatibleTransport(), new AndroidJsonFactory(), null).setRootUrl(UT.ROOT_URL).build();
}
senderId = getString(R.string.gcm_defaultSenderId);
mToken = InstanceID.getInstance(mAct).getToken(senderId, GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
mRegSvc.registToken(mToken).execute();
GcmPubSub.getInstance(mAct).subscribe(mToken, "/topics/global", null); // subscribing to all 'topics' from 'mToken'
} catch (IOException e) { e.printStackTrace(); }
}
}
// send message to EndPoints backend server
new Thread(new Runnable() {
#Override
public void run() {
if (mRegSvc != null) try {
mRegSvc.sendMsg("hello").execute();
} catch (IOException e) { e.printStackTrace(); }
}
}).start();
// receive GCM message
public class GcmListenSvc extends GcmListenerService {
#Override
public void onMessageReceived(String senderId, Bundle data) {
Log.i("_X_", data.getString("message"));
}
}
What is relevant, thought, there is also an APIs Explorer created for the project, that can be used to send messages to your Android device from any browser.
If you use this Explorer, you can see the GET, POST requests for your EndPoints backend server, i.e.
list all registered devices:
GET https://epgcm.appspot.com/_ah/api/gcmEP/v1/tokenrec?fields=items
send a message to all registered devices:
POST https://epgcm.appspot.com/_ah/api/gcmEP/v1/sendMsg/Hello%20World!
Now, you can use this knowledge to send messages to your Android device from an AppScript code as shown:
Version 1: Get list of registered devices and send a GCM message to all of them (or a filtered set).
function sendMsg() {
var msg = 'test from CODE.GS';
var url = 'https://epgcm.appspot.com/_ah/api/gcmEP/v1/tokenrec?fields=items';
var params = { method : 'get'};
var response = UrlFetchApp.fetch(url, params);
var data = JSON.parse(response.getContentText());
var regIds = [];
for (i in data.items)
regIds.push(data.items[i].token);
var payload = JSON.stringify({
'registration_ids' : regIds,
'data' : { 'message' : msg }
});
var params = {
'contentType' : 'application/json',
'headers' : {'Authorization' : 'key=AIza............................'},
'method' : 'post',
'payload' : payload
};
url = 'https://android.googleapis.com/gcm/send';
UrlFetchApp.fetch(url, params);
}
This version relies on code from an old YouTube video, and I don't know if the call to 'android.googleapis.com' is still supported (but it works).
Version 2: Use the EndPoints's 'sendMsg' directly.
function sendMsg() {
var msg = 'test from CODE.GS';
var params = { method : 'post'};
var url = 'https://demoepgcm.appspot.com/_ah/api/gcmEP/v1/sendMsg/' + encodeURIComponent(msg.trim());
UrlFetchApp.fetch(url, params);
}
I have to admit I've never written a line of JavaScript code before, so it may not be up-to-par, but I made it work as a 'proof of concept'.
I would like to get feedback about this problem from people-who-know, since there is so little published info on this specific issue.

How can google app engine create new contacts?

I'm developing a membership sign up app for an organization on Google App Engine, for new members, they can use a sign up page to become a member, is there a way in Google App Engine to add new members as gmail contacts ? So each time a new user clicks a submit button with his info, a new gmail contact is auto generated and added to my contact list [ my gmail address is registered with the GAE app ].
Here is some of my code try to do that, but it doesn't add new contacts each a submit button is pressed :
String Add_New_Contact_Url="https://www.google.com/m8/feeds/contacts/default/full";
protected void processRequest(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException
{
request.setCharacterEncoding("UTF-8");
response.setContentType("text/html; charset=UTF-8"); // UTF-8 GB18030
PrintWriter out=response.getWriter();
String Email=request.getParameter("Email");
if (Email==null || Email.trim().length()<1)
{
StrBuf=new StringBuffer("<Html><Head><Title>Signup</Title></Head>\n<Body>\n");
StrBuf.append("<P><Br><P><Br><P>\n");
StrBuf.append("<Table Border=1 Align=Center Cellpadding=8 Cellspacing=1><Tr Bgcolor=\"#0088FF\" Colspan=2><Th><Font Color=White>Sign up</Font></Th></Tr></Table>\n<P>\n");
StrBuf.append("<Center>\n");
StrBuf.append("<Form Name=Singles_Club_Signup_Form>\n");
StrBuf.append("<Table Border=1 Cellpadding=6 Cellspacing=1>\n");
...
StrBuf.append("<Tr><Td Align=Right><B><Font Size=3 Color=#0066FF>Email</Font></B></Td><Td><Input type=text name=Email size=36 /></Td></Tr>\n");
...
StrBuf.append("</Table>\n");
StrBuf.append("<P><Br><P>\n");
StrBuf.append("<Input type=submit value=Sign_Up/>\n");
StrBuf.append("</Form>\n");
StrBuf.append("</Center>\n");
StrBuf.append("</Body>\n</Html>");
}
else
{
try
{
LinkedHashMap<String,String> Key_Value_Pairs=new LinkedHashMap<String,String>();
String A_Contact=createContact(Email);
Key_Value_Pairs.put("A",A_Contact);
getFromUrlDoPost(Add_New_Contact_Url,Key_Value_Pairs); // Create new contact in Gmail account
}
catch (Exception e) { out.println(e.toString()); }
finally { if (pm!=null) pm.close(); }
}
}
String createContact(String Email)
{
return "<atom:entry xmlns:atom='http://www.w3.org/2005/Atom' xmlns:gd='http://schemas.google.com/g/2005'>\n"+
"<atom:category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/contact/2008#contact' />\n"+
"<gd:name>\n"+
"<gd:givenName>AAA</gd:givenName>\n"+
"<gd:familyName>BBB</gd:familyName>\n"+
"<gd:fullName>AAA BBB</gd:fullName>\n"+
"</gd:name>\n"+
"<atom:content type='text'>Notes</atom:content>\n"+
"<gd:email rel='http://schemas.google.com/g/2005#work' primary='true' address='"+Email+"' displayName='E. Bennet' />\n"+
"<gd:email rel='http://schemas.google.com/g/2005#home' address='liz#example.org' />\n"+
"<gd:phoneNumber rel='http://schemas.google.com/g/2005#work' primary='true'>\n"+
"(206)555-1212\n"+
"</gd:phoneNumber>\n"+
"<gd:phoneNumber rel='http://schemas.google.com/g/2005#home'>\n"+
"(206)555-1213\n"+
"</gd:phoneNumber>\n"+
"<gd:im address='liz#gmail.com' protocol='http://schemas.google.com/g/2005#GOOGLE_TALK' primary='true' rel='http://schemas.google.com/g/2005#home' />\n"+
"<gd:structuredPostalAddress rel='http://schemas.google.com/g/2005#work' primary='true'>\n"+
"<gd:city>Mountain View</gd:city>\n"+
"<gd:street>1600 Amphitheatre Pkwy</gd:street>\n"+
"<gd:region>CA</gd:region>\n"+
"<gd:postcode>94043</gd:postcode>\n"+
"<gd:country>United States</gd:country>\n"+
"<gd:formattedAddress>\n"+
"1600 Amphitheatre Pkwy Mountain View\n"+
"</gd:formattedAddress>\n"+
"</gd:structuredPostalAddress>\n"+
"</atom:entry>";
}
StringBuffer getFromUrlDoPost(String A_Url,LinkedHashMap Key_Value_Pairs) throws MalformedURLException,IOException
{
StringBuffer Text_Out=new StringBuffer(""),Text_In=new StringBuffer("");
String data="",key,value,inputLine;
try // Sending a POST Request Using a URL
{
// Construct data -- List the entries
for (Iterator it=Key_Value_Pairs.keySet().iterator();it.hasNext();)
{
key=it.next().toString();
value=Key_Value_Pairs.get(key).toString();
if (data.length()==0) data=URLEncoder.encode(key,"UTF-8")+"="+URLEncoder.encode(value,"UTF-8");
else data+="&"+URLEncoder.encode(key,"UTF-8")+"="+URLEncoder.encode(value,"UTF-8");
}
// Send data
URLConnection conn=new URL(A_Url).openConnection();
conn.setRequestProperty("Content-Type","application/atom+xml");
conn.setDoOutput(true);
OutputStreamWriter wr=new OutputStreamWriter(conn.getOutputStream());
wr.write(data);
wr.flush();
Text_In.setLength(0);
// Get the response
BufferedReader rd=new BufferedReader(new InputStreamReader(conn.getInputStream()));
while ((inputLine=rd.readLine()) != null) Text_In.append(inputLine+"\n");
wr.close();
rd.close();
}
catch (Exception e) { }
return Text_In;
}
It doesn't cause error either, what did I do wrong ? I suspect this line :
Key_Value_Pairs.put("A",A_Contact);
Because I don't know what to put in the place of "A" ?
Your users can authorize your application (via OAuth) to interact with their gmail contact list via the Contacts Data API.
I found out why : don't need to include google-collect-*.jar, source of error.

Resources