Closed m-andersen closed 4 years ago
@HeinA which authentication flow are you using? At what point are you getting the 401?
Got it sorted out. It was a miconfiguration on the App Service side.
Thanx for your prompt response though!
Regards
Hey @RyanHill-MSFT
I'm now also having difficulty in refreshing the Apple token. May I also contact you at the above mentioned email address to resolve this issue?
Thanx
Hey @RyanHill-MSFT
I'm now also having difficulty in refreshing the Apple token. May I also contact you at the above mentioned email address to resolve this issue?
Thanx
Yes you can @HeinA
@gfaraj I've reached out to the product team for any updates. EDIT: The token refresh isn't supported with generic OIDC, but the team is working on a solution to address this limitation. When more details are available, we'll share them. /cc @mattchenderson
Hi @RyanHill-MSFT -- do we have any updates on the short-lived tokens when using the Apple OIDC provider?
@RyanHill-MSFT Any update on token refresh for Apple OIDC provider?
some notes for others still struggling:
this definitely worked for me. I was getting a 401 ("you do not have permission to view this page") when I passed the token I got from the Apple API calls up to /.auth/login/apple.
My 401 was caused by an incorrect Apple Client Secret JWT (the JWT you construct using the p8 you downloaded from apple). Remember, these expire every 6 months, so if it was working, and now it's broke, that might be why!
Follow the instructions at: https://learn.microsoft.com/en-us/azure/app-service/configure-authentication-provider-apple
To generate the JWT you'll need some code, your team ID, your key ID, your p8, and your client ID.
Your Team ID and KeyId are these:
Make a new C# console app, and enable (fancy! new!) immediate execution (https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/program-structure/top-level-statements).
Use this sample code (this is the JWT generation sample code from the above link, + I added some Console.WriteLine() calls):
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Security.Cryptography;
void GetAppleClientSecret(string teamId, string clientId, string keyId, string p8key)
{
string audience = "https://appleid.apple.com";
string issuer = teamId;
string subject = clientId;
string kid = keyId;
IList<Claim> claims = new List<Claim> {
new Claim ("sub", subject)
};
CngKey cngKey = CngKey.Import(Convert.FromBase64String(p8key), CngKeyBlobFormat.Pkcs8PrivateBlob);
SigningCredentials signingCred = new SigningCredentials(
new ECDsaSecurityKey(new ECDsaCng(cngKey)),
SecurityAlgorithms.EcdsaSha256
);
JwtSecurityToken token = new JwtSecurityToken(
issuer,
audience,
claims,
DateTime.Now,
DateTime.Now.AddDays(180),
signingCred
);
token.Header.Add("kid", kid);
token.Header.Remove("typ");
Console.WriteLine($"token:\n\n{token}");
JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler();
Console.WriteLine("\n\n");
Console.WriteLine("\n----- done. Put the following into Azure, client secret setting:\n\n");
Console.WriteLine(tokenHandler.WriteToken(token));
}
GetAppleClientSecret(
teamId: "(see above, the 10-character ID in the top-right of developer.apple.com, next to your name)",
clientId: "(your client ID. I used the ID of my actual app (com.xxx.xxxapp). I didn't use the services ID. I'm not sure it matters, so long as what's specified here matches what's configured in the azure portal.)",
keyId: "(see above. This key should have Sign in with Apple as an Enabled Service)",
p8key: "(you downloaded this from apple, default filename is AuthKey_(keyId).p8. Paste in the chars between the ---BEGIN and ---END PRIVATE KEY, no line breaks.)"
);
Console.ReadLine(); // so the console stays up, allowing you to copy the key out!
I'm using these nugets:
The JWT you need is exactly that last outputted string (it'll start with eyJ... probably), with NO LINE BREAKS:
(By the way, you can paste that JWT into https://www.jstoolset.com/jwt to verify it and make note of the expiration date).
Next, go to the configuration page of your mobile app in azure, and create a new application setting. Name it anything, I named mine "signInWithAppleClientSecret", and I set its value to the JWT (again, careful there's no line breaks, leading/trailing spaces, etc. It must be exact).
Don't forget to hit save, up top!
Then, go to the Authentication page of your mobile app in azure, and Add Provider, Apple.
Your client ID in this config must match the clientID in the JWT (aka the 2nd argument to GetAppleClientSecret()). For "Client Secret Setting Name," choose the application setting you just made (i.e. signInWithAppleClientSecret).
RESTART your azure app.
On the client side, the correct way to pass what you get from the Apple SDK is, as others have pointed out, via id_token. This little detail is missing from the docs.
{"id_token": (identityToken) }
where (identityToken) is the "IdentityToken" property of the ASAuthorizationAppleIdCredential you (hopefully!) got back from your call to ASAuthorization's GetCredential method (inside your DidComplete).
Here's my (chopped up!) client side code, confirmed working:
public class SignInWithAppleLoginResults
{
public bool IsSuccess;
public string Message { get; set; }
public string IdToken { get; set; }
}
.....
public async Task<SignInWithAppleLoginResults> SignInWithAppleAsync()
{
_signInWithAppleCompletionTask = new TaskCompletionSource<SignInWithAppleLoginResults>();
var appleIdProvider = new ASAuthorizationAppleIdProvider();
var request = appleIdProvider.CreateRequest();
request.RequestedScopes = new[] { ASAuthorizationScope.Email, ASAuthorizationScope.FullName };
var authorizationController = new ASAuthorizationController(new ASAuthorizationRequest[] { request });
authorizationController.Delegate = this;
authorizationController.PresentationContextProvider = this;
authorizationController.PerformRequests();
var appleAuth = await _signInWithAppleCompletionTask.Task;
if (appleAuth.IsSuccess == false)
{
throw new Exception(appleAuth.Message);
}
// now we have the apple token... give it to azure to finish off the login.
JObject zumoPayload = new JObject
{
["id_token"] = appleAuth.IdToken
};
var signedInUser = await MobileService.LoginAsync("apple", zumoPayload);
if (signedInUser != null) Log.Information($"you are now signed-in as {signedInUser.UserId}");
// UserId will be sid:xxxxx..., and you'll have an azure token!
..... // other app-specific code to get real name etc from azure, snipped
}
And then the didComplete, for the Apple SDK:
[Export("authorizationController:didCompleteWithAuthorization:")]
public void DidComplete(ASAuthorizationController controller, ASAuthorization authorization)
{
var results = new SignInWithAppleLoginResults()
if (authorization.GetCredential<ASAuthorizationAppleIdCredential>() is ASAuthorizationAppleIdCredential appleIdCredential)
{
results.IdToken = appleIdCredential.IdentityToken.ToString();
results.IsSuccess = true;
results.Message = "Logged in!"; // this is specific to my app, ignore.
}
else
{
results.IsSuccess = false,
results.Message = "Did not receive Apple ID credentials";
}
_signInWithAppleCompletionTask.TrySetResult(results);
}
[Export("authorizationController:didCompleteWithError:")]
public void DidComplete(ASAuthorizationController controller, NSError error)
{
Log.Error($"DidComplete (apple sign in): error: {error.ToString()}");
_signInWithAppleCompletionTask.TrySetResult(new SignInWithAppleLoginResults()
{
IsSuccess = false,
Message = error.ToString()
});
}
I hope it helps!
@masonmc did you get token refresh working for apple? my tokens are lasting 1 day
Identify providers are easy to add but we have big problems trying to find out how to add Sign-in with Apple, which is now a requirement for all new apps. This link describes Azure AD B2C, but is that the same as Azure Active Directory? And how to link all this together like with Facebook. https://github.com/azure-ad-b2c/samples/tree/master/policies/sign-in-with-apple
I would like to eventually see the a token and sid:xxx from EasyAuth with Sign-in with apple. Is that possible to have all these providers be compatible or what should we expect?
Document Details
⚠ Do not edit this section. It is required for docs.microsoft.com ➟ GitHub issue linking.