Generating authentication token for APNS connection - java

I am new to vertx, and using an app server created via vertx for connection with APNS for push notifications.
I created an authProvider via
private JWTAuth createOauthProvider() {
PubSecKeyOptions pubSecKeyOptions = new PubSecKeyOptions()
.setAlgorithm("ES256").setSecretKey(*/private key from .p8 extracted as is removing unwanted part in base64*/);
return JWTAuth.create(vertx(), new JWTAuthOptions().addPubSecKey(pubSecKeyOptions));
}
and then a JWT via
private String createJwt() {
Instant now = Instant.now();
JsonObject decoded = new JsonObject()
.put("alg", "ES256")
.put("kid", "kid here")
.put("iss", "teamid here")
.put("iat", now.getEpochSecond());
String jwt = oauth2JWTProvider.generateToken(decoded,
new JWTOptions().setAlgorithm("ES256"));
return jwt;
}
Now here's my query -
Is my token creation criteria correct?
JWT created after this when send to APNS returns a 403-InvalidProviderToken.
Appreciate all the help i can get. Thanks!!

Answering my own question as i was able to get around this and just in case it helps anyone else. Just posting the createJwt() method rest everything remains same-
private String createJwt() {
Instant now = Instant.now();
JsonObject header = new JsonObject()
.put(JwtConstants.ALG, "ES256")
.put(JwtConstants.KID, "kid here");
JsonObject payload = new JsonObject()
.put(JwtConstants.ISS, "team id here")
.put(JwtConstants.IAT, now.getEpochSecond());
String jwt = oauth2JWTProvider.generateToken(payload,
new JWTOptions()
.setHeader(header)
.setAlgorithm("ES256"));
return jwt;
}

Related

How to send a voice call to multiple people with Java and Twilio

I have this method, that makes the request to the specified phone number:
public Call sendVoiceCall(String responsiblePhoneNumber, String completeName) {
Twilio.init(ACCOUNT_SID, AUTH_TOKEN);
String helloTwiml = new VoiceResponse.Builder()
.say(new Say.Builder("Whatever")
.voice(Say.Voice.ALICE).language(Say.Language.PT_BR).build())
.build().toXml();
Call call = Call.creator(
new PhoneNumber(responsiblePhoneNumber),
new PhoneNumber(twilioPhoneNumber),
new Twiml(helloTwiml))
.create();
return call;
}
I call it inside this method:
#PostMapping("/sendVoiceCall")
#Transactional
#Async
public void sendVoiceCall() {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
Optional<User> username = userRepository.findByUsername(auth.getName());
List<Dependency> uuids = dependencyRepository.returnAllContactUuid(username.orElse(null).getUuid());
uuids.forEach(contact -> {
Optional<User> user = userRepository.findByUuid(contact.getContactUuid());
voiceCallService.sendVoiceCall(user.orElse(null).getPhone(), username.get().getCompleteName());
});
log.info("There was a request to warn users responsible for: " + username.orElse(null).getCompleteName());
}
When I try to send just to one person it works, but when I try to iterate using lambda, it gives me a 200 code and makes nothing.
Thanks for your help!

Emojis not rendering properly in iOS push notifications

I have a Java Spring Boot web service and I am trying to send push notifications to an iOS device.
The problem I am facing is that the emoji text Which is directly pasted, like
String emoji = "😀";
Or its code, like
String emoji = "\uD83D\uDE0A";
it shows as ? (Question mark symbol)
I have tried getting it as bytes of UTF_8 characters like this:
byte[] emojis = user.getEmoji().getBytes(); //Here user.getEmoji() returns a collection of 2-3 emojis
String emojisAsString = new String(emojis, StandardCharsets.UTF_8);
Integer emojiCodePoint = emojisAsString.codePointAt(emojisAsString.offsetByCodePoints(0,0));
char emojiChars[] = {Character.highSurrogate(emojiCodePoint), Character.lowSurrogate(emojiCodePoint)};
But it still shows as question marks.
I also tried using UTF-8 code like "\xE2\x9A\xA1" but this one just got printed as it is on the notification.
Also when I call the notification API from postman using FCM APIs and paste emojis, it shows emojis in the notification, it just shows as question marks when done through Java web service.
This is the Push notification service code
#RequestMapping(value = "/send", method = RequestMethod.GET, produces = "application/json")
public static ResponseEntity<String> send(String message, String deviceToken, Integer type, Object response, String userNameAsTitle) {
//response.setMessage(message);
//response.setNotificationType(type);
JSONObject body = new JSONObject();
body.put("to", deviceToken);
body.put("priority", "high");
Map<String, Object> map = new HashMap<>();
map.put("title", userNameAsTitle);
map.put("body", message);
//map.put("alert", descprtion);
map.put("type", type);
map.put("badge", 1);
map.put("sound", "default");
map.put("response", response);
JSONObject notification = new JSONObject(map);
//body.put("notification", notification);
body.put("notification", notification);
HttpEntity<String> request = new HttpEntity<>(body.toString());
CompletableFuture<String> pushNotification = androidPushNotificationsService.send(request);
CompletableFuture.allOf(pushNotification).join();
try {
String firebaseResponse = pushNotification.get();
System.out.println(firebaseResponse.toString());
return new ResponseEntity<>(firebaseResponse.toString(), HttpStatus.OK);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
return new ResponseEntity<>("Push Notification ERROR!", HttpStatus.BAD_REQUEST);
}

How to use vert.x AzureADAuth?

In our company we try to start using oauth2.0 with our Azure AD Tenant using vue.js as frontend and vert.x services on the backend.
The idea would be that i want to
If i call our vert.x service with the jwt which we got from Azure AD i got a runtime exception saying: "Not enough or too many segments". The JWT has 3 segments like expected. This is how i create the AzureADAuth:
OAuth2ClientOptions opts = new OAuth2ClientOptions();
opts.setFlow(OAuth2FlowType.AUTH_JWT);
OAuth2Auth auth = AzureADAuth.create(vertx,"{{application-id}}","{{secret}}","{{tenant-id}}", opts);
Inside my handler i try to authenticate:
HttpServerRequest request = context.request();
String authorization = request.headers().get(HttpHeaders.AUTHORIZATION);
String[] parts = authorization.split(" ");
scheme = parts[0];
token = parts[1];
JsonObject creds = new JsonObject();
creds.put("token_type", scheme);
creds.put("access_token", token);
authProvider.authenticate(creds,userAsyncResult -> {
if(userAsyncResult.succeeded()){
context.next();
} else {
context.fail(401);
}
});
So after i figured out that i need to add a jwk i tried to use the AzureADAuth.discover method.
My code looks like this:
OAuth2ClientOptions optsDisc = new OAuth2ClientOptions();
optsDisc.setSite("https://login.windows.net/{tenant-id}");
optsDisc.setClientID("{application-id}");
AzureADAuth.discover(vertx, optsDisc,res -> {
if (res.succeeded()) {
if(log.isDebugEnabled()) {
log.debug("Discover succeeded.");
}
} else {
log.error("Discover failed.");
}
});
Running this code causes a "Discover failed" with the following message:
java.lang.RuntimeException: java.security.cert.CertificateException: Could not parse certificate: java.io.IOException: Empty input
So my question is how do i authenticate my user with my given bearer token with vert.x?
I obviously had a version conflict here.
I set all my dependencies to 3.6.2 and now it works. Just took me a bit to figure out how to handle the discovery and that i don't need to create a new OAuth2Auth object with AzureAdAuth after the discovery.
For future reference:
OAuth2ClientOptions optsDisc = new OAuth2ClientOptions();
opts.setClientID("{client-id}");
AzureADAuth.discover(vertx, opts,res -> {
if (res.succeeded()) {
//use res.result() to access the through discovery already created OAuth2Auth Object
log.debug("Discover succeeded.");
} else {
log.error("Discover failed.");
}
})

How to consume a RestFull service using Android Studio

I have a API using ASP.NET Web API which return a json list and receive as well, on .NET Platform to make a POST or GET I use something like :
private string UrlLocalTest = "http://192.168.0.102:3000/api/";
public async Task<HttpResponseMessage> PostWeb(Model model)
{
HttpClient client = new HttpClient();
Uri url = new Uri(string.Concat(Url, "gone/POST"));
return await client.PostAsJsonAsync(url, model);
}
public async Task<HttpResponseMessage> GET(string name)
{
var client = new HttpClient();
Uri url = new Uri(string.Concat(UrlLocalTestTwo, "/GET" + name));
var response = await client.GetAsync(url);
return response;
}
And to return a token from my WebApi using oauth2 it goes like :
public async Task<HttpResponseMessage> Authenticate(string pEmail = null, string pPassword = null)
{
var Client = new HttpClient();
var _tokenArgs = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string,string>("username",pEmail),
new KeyValuePair<string, string>("password",pPassword),
new KeyValuePair<string, string>("grant_type","password")
});
Uri url = new Uri(UrlLocalTest);
return await Client.PostAsync(url, _tokenArgs);
}
How can I perform those methods and actions using Android ? I found something close to this, but I believe is more complex on Android.
Have a look at OkHttp. It provides easy access to HTTP-based services without too much abstraction. Why do you think it will be more complex on Android?
User volley. It is very easy to use and handle.
https://developer.android.com/training/volley/simple.html

Get facebook access token with spring social FacebookConnectionFactory

I am trying to implement a Facebook Connection using Spring Social, based on this example(from spring social manual):
FacebookConnectionFactory connectionFactory =
new FacebookConnectionFactory("clientId", "clientSecret");
OAuth2Operations oauthOperations = connectionFactory.getOAuthOperations();
OAuth2Parameters params = new OAuth2Parameters();
params.setRedirectUri("https://my-callback-url");
String authorizeUrl = oauthOperations.buildAuthorizeUrl(GrantType.AUTHORIZATION_CODE, params);
response.sendRedirect(authorizeUrl);
// upon receiving the callback from the provider:
AccessGrant accessGrant = oauthOperations.exchangeForAccess(authorizationCode, "https://my-callback-url", null);
Connection<Facebook> connection = connectionFactory.createConnection(accessGrant);
My problem is that I don't know what my redirect url should be.My code is this:
#RequestMapping("/face")
public String communicate() {
FacebookConnectionFactory connectionFactory =
new FacebookConnectionFactory(clientId, clientSecret);
OAuth2Operations oauthOperations = connectionFactory.getOAuthOperations();
OAuth2Parameters params = new OAuth2Parameters();
//this remdirectUri should be another one?
params.setRedirectUri("http://dev01.spring:8080/spring/face");
String authorizeUrl = oauthOperations.buildAuthorizeUrl(GrantType.AUTHORIZATION_CODE, params);
System.out.println(authorizeUrl);
//return "redirect:"+authorizeUrl;
// upon receiving the callback from the provider:
//AccessGrant accessGrant = oauthOperations.exchangeForAccess(authorizationCode, "https://my-callback-url", null);
//Connection<Facebook> connection = connectionFactory.createConnection(accessGrant);
}
My authorizeUrl is like this(from System.out line):
https://graph.facebook.com/oauth/authorize?client_id=myId&response_type=code&redirect_uri=http%3A%2F%2Fdev01.spring%3A8080%2Fspring%2Fface
If i uncomment the line where I continue the Oauth flow redirecting to this authorizeUrl, i'm getting the following error: This webpage has a redirect loop.
So my question is, what the redirect uri should be.Thank you.
Very late edit, in the hopes it helps someone. This is my controller and the method that does the whole Oauth2 dance. I must add that this worked when the question was asked, I have no idea how it behaves now.
#Controller
public class FacebookController {
private static final String clientId = "clientIdHere"; // clientId from facebook app
private static final String clientSecret = "clientSecret here"; // clientSecret
private FacebookConnectionFactory connectionFactory; // facebookConnectionFactory
/*
* If an authorization was given by provider(code) we get an token and bind the api.
*/
#RequestMapping("/facebook/callback")
public String authorize(#RequestParam("code") String authorizationCode,Model model) {
// exchange facebook code with an access token.
AccessGrant accessGrant = connectionFactory.getOAuthOperations().exchangeForAccess(authorizationCode, "http://localhost:8080/testApp/facebook/callback", null); // not that the application was deployed at "http://localhost:8080/testApp"
// connect to facebook with the given token.
Connection<Facebook> connection = connectionFactory.createConnection(accessGrant);
// bind the api
Facebook facebook = connection.getApi();
// get user profile informations
FacebookProfile userProfile = facebook.userOperations().getUserProfile();
// At this point you have acces to the facebook api.
// For ex you can get data about the user profile like this
// create user with facebook's user accounts details.
User facebookUser = new User(userProfile.getFirstName(),
userProfile.getLastName(),
userProfile.getEmail(),
Role.ROLE_FACEBOOKUSER,
"socialuser");
return "redirect:/home";
}
}

Categories

Resources