Milos Zikic - Personal site, sharing thoughts about startups, products and engineering

Solving Cocoapods arm64 issues

You are just starting your new awesome iOS app. You have set up Podfile and all the libraries that you love. You will use Swift to code, because the functional is the way to go. Everything is set up and then you open up XCode to find out the error on build:

Undefined symbols for architecture arm64

WTF!?

Relax, the issue is with some of libraries that you like using (e.g. Crashlytics is build as 32bit pod). Ok, what now!?

In order to fix this there are 2 options:

  1. Figure out what library is the issue and recompile it or
  2. Update Build Settings and adjust Architectures to 32bit ones

The option #2 is much easier if you do not need to do something specific in your app that 32bit architecture would not support.

You can change this manually through XCode: XCode Target Architectures

So just change the value for Architectures to "armv7 armv7s" or better use the variable "$(ARCHSSTANDARD32_BIT)". Leave the Valid Architectures as they are as you for sure want to support new devices as well.

Or even better, since you are already using Cocoapods why not let them handle this. Add the post_install hook to your Podfile like this:

post_install do |installer|
  installer.project.targets.each do |target|
    target.build_configurations.each do |configuration|
      target.build_settings(configuration.name)['ARCHS'] = '$(ARCHS_STANDARD_32_BIT)'
    end
  end
end

And that's it.

NOTE: You may know this already but Cocopods still lacks Swift framework support, so you will have to combine cocoapods and checking git submodules. Though the support is coming along, join in, contribute, or be paitent..

Solving backward compatibility issues with new Android build system between Intellij Idea versions

New Android built tools based on gradle are awesome and it is great that we are heading to some form of standardization.

BUT!

Android SDK and gradle build plugin breaks compatibility between versions! And that is causing pain, especially for large teams. E.g. SDK Tools from version 23 do not include zipalign anymore and therefor android plugin 0.10.+ will not work -> workaround is to get zipalign from older sdk tools version :(

In the team we have people working in Idea 13 and some of the guys use AndroidStudio and some are on Eclipse. We need to support all of this environments and our Jenkins CI server.

In order to do this we created a small workaround so both Idea 13 and AndroidStudio devs can continue to work and utilize Idea Gradle integration.

Here is how:

  • People using Idea 14 EAP or AndroidStudio should set the following as Gradle VM Arguments:
-Didea.version=14
  • And then some changes to settings.gradle and build.gradle:

settings.gradle

// check if we are using AndStudio or Idea 14 EAP
boolean fromIdea14 = System.properties["idea.version"]?.toString().equals("14")

org.gradle.api.internal.initialization.DefaultScriptHandler.metaClass.toolsVersion = fromIdea14 ? "0.11.+" : "0.10.+"


build.gradle

buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath group: 'com.android.tools.build', name: "gradle", version: getBuildscript().toolsVersion
}
}

And that is it!

Happy hacking ;)

Grails easy REST Security

REST services did not came with a standard way of authentication like WS-Security for SOAP services. You can always turn to OAuth authentication which is great if you are providing services for 3rd parties that will utilize your user base and their data (e.g. Facebook or Twitter) but it is not that easy to integrate and it may come as an overhead if you are sharing your services with control set of clients (e.g. other businesses that will consume your services from their servers). 

Since we are talking here about mostly "controlled" environment then all the complexity can be avoided by simply using SSL and just sending client identification to know who is consuming your data. This is the approach that many are taking and simple adding an "apiKey" parameter at the end, e.g.


https://awesomeapi.api/hotels/?apiKey=

This is fine and will provide enough security, but if you are using simple apiKeys (e.g. like client name or some username) it can be easy to guess the api key and use your service as someone else (especially if you have your service documentation publicly). Easy solution is to use hash based apiKeys which are not guessable. More secure way is to add additional argument something like "password". This way it would be very hard to guess both parameters and breach your service. E.g. this can be easily achieved by adding spring-security-plugin, adding a special role for the API consumers and generate accounts for the clients.

This is perfectly good approach and you get all the power of spring security. However if you find spring security filters as an overhead to your API or want to separate regular users and api users this might not be great option. Another benefit is to have a clean separation of your APIKeys and keep track who is owning them. And if they become compromised add ability to generate new APIKeys for the same user account.

Grails filters make it very easy to support this. Just create a file called something like APIFilters.groovy in your grails-app/conf folder and add code like this:



class ApiFilters {

def filters = {
all(uri: '/**') {

def renderError = { status, message ->
boolean xml = request.getHeader("accept").contains("xml")
boolean json = request.getHeader("accept").contains("json")
if (json || !xml) {
render(status: status, contentType: 'application/json', text: '{"error":"' + message + '"}')
} else {
render(status: status, contentType: 'application/xml', text: '' + message + '')
}
return false
}
before = {
try {

String authorizationHeader = request.getHeader('authorization')?.trim()?.toLowerCase()

String key

if (authorizationHeader == null) {
// Try with api_key request parameter and render error if it's missing.
key = params.api_key
if (key == null) {
renderError(403, 'I need an authorization parameters to serve this request.')
return false
}
} else {
try {
byte[] token
if (authorizationHeader.startsWith("apikey ")) {
token = authorizationHeader.substring(7).getBytes("UTF-8");
}
key = new String(token, "UTF-8");
} catch (ignore) {
}
// Return if key is empty.
if (key == null || key.trim() == "") {
renderError(401, "Check your authorization header syntax. It should look like \"Authorization: APIKey [your_api_key]\".")
return false
}
}
// Find API key and return if it does not exist.
APIKey apiKey = APIKey.findByApiKey(key)
if (apiKey == null) {
renderError(401, 'Unknown API key.')
return false
}
} catch (Exception e) {
renderError(500, 'Darn it, please try later!')
}

}

}
}
}


And create APIKey domain object to hold your API Keys. API Keys should be some randomly generated hash so they are not guessable.

And voila, you have a perfectly secured grails REST service. Rest clients just need to pass their api keys as a parameter or in the header of the request like this:


Authorization: APIKey [your_api_key]

If for some reason you want to allow http access to your API there is now a common way to solve this by signing your message based on a shared secret between the client and the service. This is called HMAC (Hash-based Message Authentication Code). This is the approach many companies have taken like Amazon and Microsoft. This approach follows the 2-legged OAuth (keep in mind that OAuth is authorization specification and not authentication). As it adds additional complexity with calculating the hash I would always recommend going SSL only and have the API access as simple as possible (developers love simple!).

Running Servlet 3.0 applications on Heroku

Heroku comes with Jetty 7.5.4 runner which does not support servlet 3.0. However it is very easy to overcome this as Heroku lets you push your own jetty runner version easily. All you have to do is to download it to a 'server' folder in the root of your project:

mkdir server
curl http://repo1.maven.org/maven2/org/mortbay/jetty/jetty-runner/8.1.9.v20130131/jetty-runner-8.1.9.v20130131.jar > server/jetty-runner.jar

And if you like tomcat better you can do this as well. Slick!

Native Facebook SSO in Android

Android Facebook integration

Today mobile app without easy way to get inside is considered unfriendly. Users love to share the joy of using something nice with their friends and simply love to have to remember just one password. 

Facebook is a great SSO service and it is considered a "must have" feature. 

Fortunately it is easy to integrate it. There is Android Facebook SDK created by Facebook itself, but I want to draw your attention to Android Query library. It is a great asset for Android development. It contains all the little helpers that you might need during developing your super awesome apps. And of course you want to focus on getting it awesome, so AndroidQuery is a real thing to help you out. 

Apart from other things in the package there is a SSO capatibility and Facebook authentication is really easy (either through web, or native FB app). 

The process there is straight forward, and you have demos to help as well. What is not that clear is how to generate a key hash for Facebook native android app. Here is how it looks on Facebook developer page:
facebook key hash

This field will accept multiple hashes. So, for your developer certificate use following (use the password "android"): 

keytool -exportcert -alias androiddebugkey \
-keystore ~/.android/debug.keystore | openssl sha1 -binary \
| openssl enc -a -e


And for your production builds you can generate key hash by executing following over your p12 certificate


keytool -export -alias com.yourappname -storetype pkcs12 \
-keystore cert/certificate.p12 | openssl sha1 -binary \
| openssl enc -a -e


"com.yourappname" is your keyalias. You can find out this one by executing

keytool -list -storetype pkcs12 -keystore cert/certificate.p12 -v


Happy coding!