I would like to use authentication via google play games but always after second login or linking request(first was successful) a got:
Firebase.FirebaseException: An internal error has occurred. [ Error getting access token from GOOGLE_PLAY_GAMES, OAuth2 redirect uri is:http://localhost, response: OAuth2TokenResponse{params: error=invalid_grant&error_description=Bad%20Request, httpMetadata: HttpMetadata{status=400, cachePolicy=NO_CACHE, cacheDuration=null, cacheImmutable=false, staleWhileRevalidate=null, filename=null, lastModified=null, headers=HTTP/1.1 200 OK, cookieList=[]}} ]
When I delete a user, the login works correctly again.
Should I set something in firebase console to solve this problem?
Auth to GPG scripts:
public void Init()
{
PlayGamesHelperObject.CreateObject();
PlayGamesHelperObject.RunOnGameThread(() =>
{
PlayGamesClientConfiguration config = new PlayGamesClientConfiguration.Builder()
.RequestServerAuthCode(false)
.Build();
PlayGamesPlatform.DebugLogEnabled = true;
PlayGamesPlatform.InitializeInstance(config);
Social.Active = PlayGamesPlatform.Activate();
});
}
public void Authenticate(Action<bool, ILocalUser, string> onAuth)
{
if (Social.localUser == null)
{
onAuth.Invoke(false, Social.localUser, string.Empty);
return;
}
if (Social.localUser.authenticated)
{
onAuth.Invoke(true, Social.localUser, PlayGamesPlatform.Instance.GetServerAuthCode());
return;
}
PlayGamesHelperObject.RunOnGameThread(() =>
{
Social.Active.Authenticate(Social.localUser, (status)=>
{
onAuth.Invoke(status, Social.localUser, PlayGamesPlatform.Instance.GetServerAuthCode());
});
});
}
On Auth Invoke:
private FirebaseUser User { get; set; }
private GoogleAuth Auth { get; set; }
event Action<Exception> onSingInFailed = delegate { };
event Action<FirebaseUser> onSignInSocials = delegate { };
event Action<FirebaseUser> onLinkInSocials = delegate { };
public void OnSocialsLogin(bool status, ILocalUser user, string authCode)
{
if(status)
{
Credential credential = PlayGamesAuthProvider.GetCredential(authCode);
if (User == null)
Auth.SignInWithCredential(credential, onSignInSocials, onSingInFailed);
else
Auth.LinkWithCredential(User, credential, onLinkInSocials, (exc) =>
{
onLinkFailed.Invoke(exc);
Auth.SignInWithCredential(credential, onSignInSocials, onSingInFailed);
});
}
}
Part of GoogleAuth class:
private static FirebaseAuth Auth { get; set; }
public void SignInWithCredential(Credential credential, Action<FirebaseUser> onSignIn, Action<Exception> onFailure, Action onCanceled = default(Action))
{
if (onCanceled == null)
onCanceled = delegate { };
Auth.SignInWithCredentialAsync(credential).ContinueWith(task =>
{
if (task.IsCanceled)
onCanceled.Invoke();
else if (task.IsFaulted)
onFailure.Invoke(task.Exception);
else if (task.IsCompleted)
onSignIn.Invoke(task.Result);
});
}
public void LinkWithCredential(FirebaseUser user, Credential credential, Action<FirebaseUser> onLinkIn, Action<Exception> onFailure, Action onCanceled = default(Action))
{
if (onCanceled == null)
onCanceled = delegate { };
user.LinkWithCredentialAsync(credential).ContinueWith(task =>
{
if (task.IsCanceled)
onCanceled.Invoke();
else if (task.IsFaulted)
onFailure.Invoke(task.Exception);
else if (task.IsCompleted)
onLinkIn.Invoke(task.Result);
});
}
Related
I am integrating Unity Facebook SDK to a project, right now I am making a log-in system. I have written a script, attached it to an object on a scene, created a button, added the FbLogin method as a listener of OnClick UnityEvent of my button and built an app for Android. Also I have pasted all the needed keys and tokens.
using System.Collections.Generic;
using UnityEngine;
using Facebook.Unity;
class FacebookLoginSystem
{
private void Awake()
{
FB.Init(SetInit, OnHideUnity);
}
void SetInit()
{
if (FB.IsLoggedIn)
{
Debug.Log("Logged in Successfuly!");
}
else
{
Debug.Log("FB is not loggid in");
}
}
void OnHideUnity(bool isGameShown)
{
if (isGameShown)
{
Time.timeScale = 1;
}
else
{
Time.timeScale = 0;
}
}
public void FbLogin()
{
List<string> permessions = new List<string>();
permessions.Add("public_profile");
FB.LogInWithReadPermissions(permessions, AuthCallResult);
}
private void AuthCallResult(ILoginResult result)
{
if (result.Error != null)
{
Debug.Log(result.Error);
}
else
{
if (FB.IsLoggedIn)
{
Debug.Log("FB logged in");
Debug.Log(result.RawResult);
FB.API("/me?fields=first_name", HttpMethod.GET, callbackData);
}
else
{
Debug.Log("Login Failed!");
}
}
}
}
But when I press the button in my build, I get this. ("Something went wrong, we are working on it...")
Tell me, please, why does it happen?
This happens when I press the button
UPD:
I have replaced the methods FbLogin and AuthCallback with these versions. Also I added a serialized field TextForLogging to see my logs in Build, and it tells me that "User cancelled login".
public void FbLogin()
{
var perms = new List<string>() { "public_profile", "email" };
FB.LogInWithReadPermissions(perms, AuthCallback);
}
private void AuthCallback(ILoginResult result)
{
if (FB.IsLoggedIn)
{
// AccessToken class will have session details
var aToken = Facebook.Unity.AccessToken.CurrentAccessToken;
// Print current access token's User ID
Debug.Log(aToken.UserId);
TextForLogging.text += $"\n{aToken.UserId}";
// Print current access token's granted permissions
foreach (string perm in aToken.Permissions)
{
Debug.Log(perm);
TextForLogging.text += $"\n{perm}";
}
FB.API("/me?fields=first_name", HttpMethod.GET, callbackData);
}
else
{
Debug.Log("User cancelled login");
TextForLogging.text += "\nUser cancelled login";
}
}
I am trying to get heart rate data from Google Fit using this codes:
void addBPM(List<FitData> results) {
setState(() {
results.where((data) => !data.userEntered).forEach((result) =>
_heartBPM = result.value.round());
});
}
void clearBPM() {
setState(() {
_heartBPM = 0;
});
}
void revokePermissions() async {
try {
await FitKit.revokePermissions();
permissions = await FitKit.hasPermissions(DataType.values);
print('revokePermissions: success');
} catch (e) {
print('revokePermissions: $e');
}
}
void read() async {
try {
permissions = await FitKit.requestPermissions(DataType.values);
if (!permissions) {
print('requestPermissions: failed');
setState(() {
bodyHBPM = '0';
});
} else {
if(await FitKit.requestPermissions(DataType.values)){
final now = DateTime.now();
final startOfDay = DateTime(now.year, now.month, now.day);
final results = await FitKit.read(
DataType.HEART_RATE,
dateFrom: startOfDay,
dateTo: now,
);
startTimer();
// print(results);
clearBPM();
addBPM(results);
}
print('readAll: success');
}
} catch (e) {
print('readAll: $e');
}
}
It was successful a week ago until I ran it again today and got this error:
readAll: PlatformException(FitKit, 5000: Application needs OAuth consent from the user, null, null)
What am I missing? The OAuth credentials have been created in the Google Console and it hasn't been changed since the last time I got it working.
I need help with Google Play Games plugin in unity.
My game have some scenes (1 - menu, 5 - game scenes). I downloaded plugin and write code, that initializing play games and sign user in. After this, I'm using firebase initialization and login with Play Games.
Everything works fine, when I'm starting my game (I checked logs with logcat and it shows my login and message that sign in was successful both for firebase and play games services). My script that controls firebase and google play service contains DontDestroyOnLoad and it Destroys duplicates.
When I'm returning from game scene to menu again, logcat saying that that was error and it can't login. I can press log out (on button) and log in again, and it will be good.
So, can someone answer me question, should my PlayServices walk to other scenes with DontDestroyOnLoad, or it stores data somewhere in Unity libraries (SocialPlatform)? I can't submit achievements on game scene and I can't doing other things with this...
Thanks
using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading.Tasks;
using UnityEngine;
using GooglePlayGames;
using GooglePlayGames.BasicApi;
using Firebase;
using Firebase.Auth;
using Firebase.Analytics;
using UnityEngine.SocialPlatforms;
using UnityEngine.SceneManagement;
using TMPro;
public class GooglePlayServices : MonoBehaviour
{
private GPG_CloudSaveSystem cloudSaveSystem = new GPG_CloudSaveSystem();
private string authCode;
private bool firebaseInitialized;
DependencyStatus dependencyStatus = DependencyStatus.UnavailableOther;
public static GooglePlayServices instance;
private bool isFirebaseLogged, isPlayGamesLogged;
FirebaseAuth auth;
FirebaseUser user;
private string userNametest, userNameId;
void Awake()
{
if (instance == null)
{
instance = this;
DontDestroyOnLoad(this.gameObject);
}
else
{
DestroyImmediate(gameObject);
}
auth = FirebaseAuth.DefaultInstance;
PlayGamesClientConfiguration config = new
PlayGamesClientConfiguration.Builder()
.EnableSavedGames()
.RequestServerAuthCode(false)
.Build();
// Enable debugging output (recommended)
PlayGamesPlatform.DebugLogEnabled = true;
// Initialize and activate the platform
PlayGamesPlatform.InitializeInstance(config);
PlayGamesPlatform.Activate();
if (!isPlayGamesLogged)
{
PlayGamesPlatform.Instance.Authenticate(SignInCallback, false);
}
}
private void Start()
{
Debug.Log("User name: " + userNametest + " | User ID: " + userNameId);
}
void LoginFirebase()
{
if (Social.localUser.authenticated)
{
authCode = PlayGamesPlatform.Instance.GetServerAuthCode();
}
else
{
PlayGamesPlatform.Instance.Authenticate(SignInCallback, false);
authCode = PlayGamesPlatform.Instance.GetServerAuthCode();
}
//FirebaseAuth auth = FirebaseAuth.DefaultInstance;
FirebaseAnalytics.SetAnalyticsCollectionEnabled(true);
// Set the user's sign up method.
FirebaseAnalytics.SetUserProperty(
FirebaseAnalytics.UserPropertySignUpMethod,
"PlayGames");
Credential credential = PlayGamesAuthProvider.GetCredential(authCode);
auth.SignInWithCredentialAsync(credential).ContinueWith(task =>
{
if (task.IsCanceled)
{
Debug.LogError("SignInWithCredentialAsync was canceled.");
return;
}
if (task.IsFaulted)
{
Debug.LogError("SignInWithCredentialAsync encountered an error: " + task.Exception);
return;
}
FirebaseUser newUser = task.Result;
userNametest = newUser.DisplayName;
userNameId = newUser.UserId;
Debug.LogFormat("User signed in successfully: {0} ({1})",
newUser.DisplayName, newUser.UserId);
// Set the user ID.
FirebaseAnalytics.SetUserId(newUser.UserId);
isFirebaseLogged = true;
});
// Set default session duration values.
FirebaseAnalytics.SetMinimumSessionDuration(new TimeSpan(0, 0, 10));
FirebaseAnalytics.SetSessionTimeoutDuration(new TimeSpan(0, 30, 0));
firebaseInitialized = true;
}
public void EventLevelFinished(int levelNumber)
{
string eventLog = "Level_finished_" + (levelNumber + 1).ToString();
switch (levelNumber)
{
case 2:
{
FirebaseAnalytics.LogEvent(eventLog);
break;
}
case 9:
{
FirebaseAnalytics.LogEvent(eventLog);
break;
}
case 19:
{
FirebaseAnalytics.LogEvent(eventLog);
break;
}
case 29:
{
FirebaseAnalytics.LogEvent(eventLog);
break;
}
case 39:
{
FirebaseAnalytics.LogEvent(eventLog);
break;
}
case 49:
{
FirebaseAnalytics.LogEvent(eventLog);
break;
}
case 59:
{
FirebaseAnalytics.LogEvent(eventLog);
break;
}
}
}
public void EventLogCustomEvent(string log)
{
FirebaseAnalytics.LogEvent(log);
}
public string GetFirebaseUser()
{
return user.DisplayName + " | " + user.UserId;
}
public void SaveToCloud()
{
JsonToCloud.instance.BuildSaveString();
cloudSaveSystem.saveString = Prefs.CloudSaveString;
cloudSaveSystem.SaveToCloud();
}
public void LoadFromCloud()
{
cloudSaveSystem.LoadFromCloud();
Prefs.CloudSaveString = cloudSaveSystem.saveString;
JsonToCloud.instance.StringToData();
SceneManager.LoadScene(SceneManager.GetActiveScene().name);
}
public void ShowSavedGames()
{
cloudSaveSystem.showUI();
}
public void AnalyticsLogin()
{
FirebaseAnalytics.LogEvent(FirebaseAnalytics.EventLogin);
}
public void AnalyticsProgress()
{
FirebaseAnalytics.LogEvent("progress", "percent", 0.4f);
}
void InitializeFirebase()
{
FirebaseAnalytics.SetAnalyticsCollectionEnabled(true);
// Set the user's sign up method.
FirebaseAnalytics.SetUserProperty(
FirebaseAnalytics.UserPropertySignUpMethod,
"PlayGames");
// Set the user ID.
FirebaseAnalytics.SetUserId("uber_user_510");
// Set default session duration values.
FirebaseAnalytics.SetMinimumSessionDuration(new TimeSpan(0, 0, 10));
FirebaseAnalytics.SetSessionTimeoutDuration(new TimeSpan(0, 30, 0));
firebaseInitialized = true;
}
public void ShowAchievements()
{
if (PlayGamesPlatform.Instance.localUser.authenticated)
{
PlayGamesPlatform.Instance.ShowAchievementsUI();
}
else
{
Debug.Log("Cannot show Achievements, not logged in");
}
}
public void SignIn()
{
if (!PlayGamesPlatform.Instance.localUser.authenticated)
{
// Sign in with Play Game Services, showing the consent dialog
// by setting the second parameter to isSilent=false.
PlayGamesPlatform.Instance.Authenticate(SignInCallback, false);
}
else
{
// Sign out of play games
PlayGamesPlatform.Instance.SignOut();
}
AnalyticsLogin();
}
public void SignInCallback(bool success)
{
if (success)
{
isPlayGamesLogged = true;
Debug.Log("(Lollygagger) Signed in!");
authCode = PlayGamesPlatform.Instance.GetServerAuthCode();
////////////////////////////////
FirebaseApp.CheckAndFixDependenciesAsync().ContinueWith(task =>
{
dependencyStatus = task.Result;
if (dependencyStatus == DependencyStatus.Available)
{
if (!isFirebaseLogged)
{
LoginFirebase();
}
}
else
{
Debug.LogError(
"Could not resolve all Firebase dependencies: " + dependencyStatus);
}
});
/////////////////////////////////////////
}
else
{
Debug.Log("(Lollygagger) Sign-in failed...");
}
}
}
One guy on github issues answered me, that there is no need to use DontDestroyOnLoad, just use once at main scene and that's all
I am developing a messaging application for Android and I am using an Azure Web API as my backend which connects to an Azure SQL DB. I am trying to get the service to allow users to log in and proceed through the application with an identity. I want to use Individual User Accounts to do this but I do not know how.
I have been through every piece of documentation on the internet and yet I am still at a loss on how to receive a token from the service and use it to access auhtorised resources.
If someone could please highlight the appropriate methods I need to call from the generated classes as well as methods I should write myself, that would be very helpful!
This is the Account Controller that was generated:
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Security.Claims;
using System.Security.Cryptography;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
using Microsoft.AspNet.Identity.Owin;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Cookies;
using Microsoft.Owin.Security.OAuth;
using AcademicAssistant.Models;
using AcademicAssistant.Providers;
using AcademicAssistant.Results;
namespace AcademicAssistant.Controllers
{
[Authorize]
[RoutePrefix("api/Account")]
public class AccountController : ApiController
{
private const string LocalLoginProvider = "Local";
private ApplicationUserManager _userManager;
public AccountController()
{
}
public AccountController(ApplicationUserManager userManager,
ISecureDataFormat<AuthenticationTicket> accessTokenFormat)
{
UserManager = userManager;
AccessTokenFormat = accessTokenFormat;
}
public ApplicationUserManager UserManager
{
get
{
return _userManager ?? Request.GetOwinContext().GetUserManager<ApplicationUserManager>();
}
private set
{
_userManager = value;
}
}
public ISecureDataFormat<AuthenticationTicket> AccessTokenFormat { get; private set; }
// GET api/Account/UserInfo
[HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)]
[Route("UserInfo")]
public UserInfoViewModel GetUserInfo()
{
ExternalLoginData externalLogin = ExternalLoginData.FromIdentity(User.Identity as ClaimsIdentity);
return new UserInfoViewModel
{
Email = User.Identity.GetUserName(),
HasRegistered = externalLogin == null,
LoginProvider = externalLogin != null ? externalLogin.LoginProvider : null
};
}
// POST api/Account/Logout
[Route("Logout")]
public IHttpActionResult Logout()
{
Authentication.SignOut(CookieAuthenticationDefaults.AuthenticationType);
return Ok();
}
// GET api/Account/ManageInfo?returnUrl=%2F&generateState=true
[Route("ManageInfo")]
public async Task<ManageInfoViewModel> GetManageInfo(string returnUrl, bool generateState = false)
{
IdentityUser user = await UserManager.FindByIdAsync(User.Identity.GetUserId());
if (user == null)
{
return null;
}
List<UserLoginInfoViewModel> logins = new List<UserLoginInfoViewModel>();
foreach (IdentityUserLogin linkedAccount in user.Logins)
{
logins.Add(new UserLoginInfoViewModel
{
LoginProvider = linkedAccount.LoginProvider,
ProviderKey = linkedAccount.ProviderKey
});
}
if (user.PasswordHash != null)
{
logins.Add(new UserLoginInfoViewModel
{
LoginProvider = LocalLoginProvider,
ProviderKey = user.UserName,
});
}
return new ManageInfoViewModel
{
LocalLoginProvider = LocalLoginProvider,
Email = user.UserName,
Logins = logins,
ExternalLoginProviders = GetExternalLogins(returnUrl, generateState)
};
}
// POST api/Account/ChangePassword
[Route("ChangePassword")]
public async Task<IHttpActionResult> ChangePassword(ChangePasswordBindingModel model)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
IdentityResult result = await UserManager.ChangePasswordAsync(User.Identity.GetUserId(), model.OldPassword,
model.NewPassword);
if (!result.Succeeded)
{
return GetErrorResult(result);
}
return Ok();
}
// POST api/Account/SetPassword
[Route("SetPassword")]
public async Task<IHttpActionResult> SetPassword(SetPasswordBindingModel model)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
IdentityResult result = await UserManager.AddPasswordAsync(User.Identity.GetUserId(), model.NewPassword);
if (!result.Succeeded)
{
return GetErrorResult(result);
}
return Ok();
}
// POST api/Account/AddExternalLogin
[Route("AddExternalLogin")]
public async Task<IHttpActionResult> AddExternalLogin(AddExternalLoginBindingModel model)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
Authentication.SignOut(DefaultAuthenticationTypes.ExternalCookie);
AuthenticationTicket ticket = AccessTokenFormat.Unprotect(model.ExternalAccessToken);
if (ticket == null || ticket.Identity == null || (ticket.Properties != null
&& ticket.Properties.ExpiresUtc.HasValue
&& ticket.Properties.ExpiresUtc.Value < DateTimeOffset.UtcNow))
{
return BadRequest("External login failure.");
}
ExternalLoginData externalData = ExternalLoginData.FromIdentity(ticket.Identity);
if (externalData == null)
{
return BadRequest("The external login is already associated with an account.");
}
IdentityResult result = await UserManager.AddLoginAsync(User.Identity.GetUserId(),
new UserLoginInfo(externalData.LoginProvider, externalData.ProviderKey));
if (!result.Succeeded)
{
return GetErrorResult(result);
}
return Ok();
}
// POST api/Account/RemoveLogin
[Route("RemoveLogin")]
public async Task<IHttpActionResult> RemoveLogin(RemoveLoginBindingModel model)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
IdentityResult result;
if (model.LoginProvider == LocalLoginProvider)
{
result = await UserManager.RemovePasswordAsync(User.Identity.GetUserId());
}
else
{
result = await UserManager.RemoveLoginAsync(User.Identity.GetUserId(),
new UserLoginInfo(model.LoginProvider, model.ProviderKey));
}
if (!result.Succeeded)
{
return GetErrorResult(result);
}
return Ok();
}
// GET api/Account/ExternalLogin
[OverrideAuthentication]
[HostAuthentication(DefaultAuthenticationTypes.ExternalCookie)]
[AllowAnonymous]
[Route("ExternalLogin", Name = "ExternalLogin")]
public async Task<IHttpActionResult> GetExternalLogin(string provider, string error = null)
{
if (error != null)
{
return Redirect(Url.Content("~/") + "#error=" + Uri.EscapeDataString(error));
}
if (!User.Identity.IsAuthenticated)
{
return new ChallengeResult(provider, this);
}
ExternalLoginData externalLogin = ExternalLoginData.FromIdentity(User.Identity as ClaimsIdentity);
if (externalLogin == null)
{
return InternalServerError();
}
if (externalLogin.LoginProvider != provider)
{
Authentication.SignOut(DefaultAuthenticationTypes.ExternalCookie);
return new ChallengeResult(provider, this);
}
ApplicationUser user = await UserManager.FindAsync(new UserLoginInfo(externalLogin.LoginProvider,
externalLogin.ProviderKey));
bool hasRegistered = user != null;
if (hasRegistered)
{
Authentication.SignOut(DefaultAuthenticationTypes.ExternalCookie);
ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(UserManager,
OAuthDefaults.AuthenticationType);
ClaimsIdentity cookieIdentity = await user.GenerateUserIdentityAsync(UserManager,
CookieAuthenticationDefaults.AuthenticationType);
AuthenticationProperties properties = ApplicationOAuthProvider.CreateProperties(user.UserName);
Authentication.SignIn(properties, oAuthIdentity, cookieIdentity);
}
else
{
IEnumerable<Claim> claims = externalLogin.GetClaims();
ClaimsIdentity identity = new ClaimsIdentity(claims, OAuthDefaults.AuthenticationType);
Authentication.SignIn(identity);
}
return Ok();
}
// GET api/Account/ExternalLogins?returnUrl=%2F&generateState=true
[AllowAnonymous]
[Route("ExternalLogins")]
public IEnumerable<ExternalLoginViewModel> GetExternalLogins(string returnUrl, bool generateState = false)
{
IEnumerable<AuthenticationDescription> descriptions = Authentication.GetExternalAuthenticationTypes();
List<ExternalLoginViewModel> logins = new List<ExternalLoginViewModel>();
string state;
if (generateState)
{
const int strengthInBits = 256;
state = RandomOAuthStateGenerator.Generate(strengthInBits);
}
else
{
state = null;
}
foreach (AuthenticationDescription description in descriptions)
{
ExternalLoginViewModel login = new ExternalLoginViewModel
{
Name = description.Caption,
Url = Url.Route("ExternalLogin", new
{
provider = description.AuthenticationType,
response_type = "token",
client_id = Startup.PublicClientId,
redirect_uri = new Uri(Request.RequestUri, returnUrl).AbsoluteUri,
state = state
}),
State = state
};
logins.Add(login);
}
return logins;
}
// POST api/Account/Register
[AllowAnonymous]
public async Task<IHttpActionResult> Register(RegisterBindingModel model)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var user = new ApplicationUser() { UserName = model.Email, Email = model.Email };
IdentityResult result = await UserManager.CreateAsync(user, model.Password);
if (!result.Succeeded)
{
return GetErrorResult(result);
}
return Ok();
}
// POST api/Account/RegisterExternal
[OverrideAuthentication]
[HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)]
[Route("RegisterExternal")]
public async Task<IHttpActionResult> RegisterExternal(RegisterExternalBindingModel model)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var info = await Authentication.GetExternalLoginInfoAsync();
if (info == null)
{
return InternalServerError();
}
var user = new ApplicationUser() { UserName = model.Email, Email = model.Email };
IdentityResult result = await UserManager.CreateAsync(user);
if (!result.Succeeded)
{
return GetErrorResult(result);
}
result = await UserManager.AddLoginAsync(user.Id, info.Login);
if (!result.Succeeded)
{
return GetErrorResult(result);
}
return Ok();
}
protected override void Dispose(bool disposing)
{
if (disposing && _userManager != null)
{
_userManager.Dispose();
_userManager = null;
}
base.Dispose(disposing);
}
#region Helpers
private IAuthenticationManager Authentication
{
get { return Request.GetOwinContext().Authentication; }
}
private IHttpActionResult GetErrorResult(IdentityResult result)
{
if (result == null)
{
return InternalServerError();
}
if (!result.Succeeded)
{
if (result.Errors != null)
{
foreach (string error in result.Errors)
{
ModelState.AddModelError("", error);
}
}
if (ModelState.IsValid)
{
// No ModelState errors are available to send, so just return an empty BadRequest.
return BadRequest();
}
return BadRequest(ModelState);
}
return null;
}
private class ExternalLoginData
{
public string LoginProvider { get; set; }
public string ProviderKey { get; set; }
public string UserName { get; set; }
public IList<Claim> GetClaims()
{
IList<Claim> claims = new List<Claim>();
claims.Add(new Claim(ClaimTypes.NameIdentifier, ProviderKey, null, LoginProvider));
if (UserName != null)
{
claims.Add(new Claim(ClaimTypes.Name, UserName, null, LoginProvider));
}
return claims;
}
public static ExternalLoginData FromIdentity(ClaimsIdentity identity)
{
if (identity == null)
{
return null;
}
Claim providerKeyClaim = identity.FindFirst(ClaimTypes.NameIdentifier);
if (providerKeyClaim == null || String.IsNullOrEmpty(providerKeyClaim.Issuer)
|| String.IsNullOrEmpty(providerKeyClaim.Value))
{
return null;
}
if (providerKeyClaim.Issuer == ClaimsIdentity.DefaultIssuer)
{
return null;
}
return new ExternalLoginData
{
LoginProvider = providerKeyClaim.Issuer,
ProviderKey = providerKeyClaim.Value,
UserName = identity.FindFirstValue(ClaimTypes.Name)
};
}
}
private static class RandomOAuthStateGenerator
{
private static RandomNumberGenerator _random = new RNGCryptoServiceProvider();
public static string Generate(int strengthInBits)
{
const int bitsPerByte = 8;
if (strengthInBits % bitsPerByte != 0)
{
throw new ArgumentException("strengthInBits must be evenly divisible by 8.", "strengthInBits");
}
int strengthInBytes = strengthInBits / bitsPerByte;
byte[] data = new byte[strengthInBytes];
_random.GetBytes(data);
return HttpServerUtility.UrlTokenEncode(data);
}
}
#endregion
}
}
This is the message controller I wrote:
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.Http.Description;
using AcademicAssistant.Models;
namespace AcademicAssistant.Controllers
{
[Authorize]
public class MessagesController : ApiController
{
private AcademicAssistantContext db = new AcademicAssistantContext();
// GET: api/Messages
[Authorize]
public IQueryable<Message> GetMessages()
{
return db.Messages;
}
// GET: api/Messages/5
[Authorize]
[ResponseType(typeof(Message))]
public async Task<IHttpActionResult> GetMessage(int id)
{
Message message = await db.Messages.FindAsync(id);
if (message == null)
{
return NotFound();
}
return Ok(message);
}
// PUT: api/Messages/5
[Authorize]
[ResponseType(typeof(void))]
public async Task<IHttpActionResult> PutMessage(int id, Message message)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
if (id != message.MessageID)
{
return BadRequest();
}
db.Entry(message).State = EntityState.Modified;
try
{
await db.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!MessageExists(id))
{
return NotFound();
}
else
{
throw;
}
}
return StatusCode(HttpStatusCode.NoContent);
}
// POST: api/Messages
[Authorize]
[ResponseType(typeof(Message))]
public async Task<IHttpActionResult> PostMessage(Message message)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
db.Messages.Add(message);
await db.SaveChangesAsync();
return CreatedAtRoute("DefaultApi", new { id = message.MessageID }, message);
}
// DELETE: api/Messages/5
[Authorize]
[ResponseType(typeof(Message))]
public async Task<IHttpActionResult> DeleteMessage(int id)
{
Message message = await db.Messages.FindAsync(id);
if (message == null)
{
return NotFound();
}
db.Messages.Remove(message);
await db.SaveChangesAsync();
return Ok(message);
}
[Authorize]
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
[Authorize]
private bool MessageExists(int id)
{
return db.Messages.Count(e => e.MessageID == id) > 0;
}
}
}
I'm trying to implement InAppBilling (Android) subscription. I'm trying to use component (Xamarin.InAppBilling). I can purchase the subscription but when I trying to get purchases item by subcription, nothing returns for me. How are you implementing IAB (Android) subscription? Someone have a example?
[EDITED]
public class PurchaseManager : IPlayListener
{
MLActivity2 _act;
BillingService m_service;
int m_requestId = 1;
//String _productId = "subscription.test";
//atributos IAB
String _publicKey = "";
String _productId = "";
public bool _premium;
public PurchaseManager(MLActivity2 act)
{
_act = act;
IniciarPurchase();
}
public void OnActivityResult (int requestCode, Result resultCode, Intent data)
{
m_service.HandleActivityResult(requestCode, (int)resultCode, data);
}
public void Finalizar()
{
if (m_service != null)
m_service.Dispose();
}
//Process referentes a IAB
private void IniciarPurchase ()
{
Security.ExpectSignature = false;
m_service = new BillingService(_act, this, _publicKey);
var connTask = m_service.Connect();
//Load inventory on start-up
connTask.ContinueWith(t =>
{
if (t.Result)
{
VerificarAssinatura();
}
});
}
public void Connected()
{
}
public void Disconnected()
{
}
private void VerificarAssinatura()
{
//Existing purchases
m_service.SendRequest<GetPurchasesResponse>(new GetPurchases(play.billing.v3.Consts.ITEM_TYPE_SUBS, m_requestId++)).ContinueWith(tGP =>
{
_act.RunOnUiThread(() =>
{
if (tGP.Result.Success)
{
foreach (Purchase item in tGP.Result.PurchasedItems)
MLActivity2.UiShowToast(_act, "", "Order id" + item.OrderId, true);
if (tGP.Result.PurchasedItems.Count == 0)
MLActivity2.UiShowToast(_act, "", "nao tem item", true);
}
else
MLActivity2.UiShowToast(_act, _act.GetString(Resource.String.msg_erro), "Purchases request failure. Error: " + tGP.Result.Message, false);
});
});
//Existing purchases
m_service.SendRequest<GetPurchasesResponse>(new GetPurchases(play.billing.v3.Consts.ITEM_TYPE_INAPP, m_requestId++)).ContinueWith(tGP =>
{
_act.RunOnUiThread(() =>
{
if (tGP.Result.Success)
{
foreach (Purchase item in tGP.Result.PurchasedItems)
MLActivity2.UiShowToast(_act, "", "Order id" + item.OrderId, true);
if (tGP.Result.PurchasedItems.Count == 0)
MLActivity2.UiShowToast(_act, "", "nao tem item", true);
}
else
MLActivity2.UiShowToast(_act, _act.GetString(Resource.String.msg_erro), "2222Purchases request failure. Error: " + tGP.Result.Message, false);
});
});
}
public void JaPossuiAssinatura()
{
MLActivity2.UiShowToast(_act, _act.GetString(Resource.String.assinatura_japossui_titulo), _act.GetString(Resource.String.assinatura_japossui_texto), true);
}
public void Comprar ()
{
var req = new Buy(_productId, m_requestId++);
m_service.SendRequest<Response>(req).ContinueWith(t =>
{
_act.RunOnUiThread(() =>
{
if (t.Result.Success)
VerificarAssinatura();
else
MLActivity2.UiShowToast(_act, _act.GetString(Resource.String.msg_erro), "Purchases request failure. Error: " + t.Result.Message, false);
});
});
}
void CompraComSucesso()
{
MLActivity2.UiShowToast(_act, _act.GetString(Resource.String.assinatura_sucesso_titulo), _act.GetString(Resource.String.assinatura_sucesso_texto), true);
}
void ErroNaCompra()
{
//MLActivity2.UiShowToast(_act, _act.GetString(Resource.String.msg_erro), _act.GetString(Resource.String.assinatura_problema), false);
}
}
Adding a code snippet always helps to get the right answer faster. Don't forget it next time ;)
When you query purchases, make sure you use correct item type: subscription (and not the product). If you have both, you have to do two queries - one for products and one for subscriptions.