Repository: box/box-python-sdk

Issue:
Private key file throws error when trying load_pem_private_key
I'm running python-3.5.0 on OS X 10.11.5. When trying to use JWT Authorization, creating a JWTAuth object fails with:

```
Traceback (most recent call last):
  File "<stdin>", line 6, in <module>
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/boxsdk/auth/jwt_auth.py", line 102, in __init__
    backend=default_backend(),
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/cryptography/hazmat/primitives/serialization.py", line 20, in load_pem_private_key
    return backend.load_pem_private_key(data, password)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/cryptography/hazmat/backends/multibackend.py", line 289, in load_pem_private_key
    return b.load_pem_private_key(data, password)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/cryptography/hazmat/backends/openssl/backend.py", line 1069, in load_pem_private_key
    password,
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/cryptography/hazmat/backends/openssl/backend.py", line 1247, in _load_key
    mem_bio = self._bytes_to_bio(data)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/cryptography/hazmat/backends/openssl/backend.py", line 477, in _bytes_to_bio
    data_char_p = self._ffi.new("char[]", data)
TypeError: initializer for ctype 'char[]' must be a bytes or list or tuple, not str
```

The default `openssl` backend is what seems to be the problem, but I'm not sure if I'm missing a step. [This issue](https://github.com/pyca/pyopenssl/issues/15) suggests that this is an expected result.

I have tried a workaround that seems to work, but there are some issues there, as well.

Discussion:
boxcla: Verified that @jmoldow has signed the CLA. Thanks for the pull request!
Jeff-Meadows: 👍 

Patch:
diff --git a/HISTORY.rst b/HISTORY.rst
index e7ca71f..25def3f 100644
--- a/HISTORY.rst
+++ b/HISTORY.rst
@@ -6,7 +6,12 @@ Release History
 Upcoming
 ++++++++
 
-1.5.2
+1.5.3
+++++++++++++++++++
+
+- Bugfix so that ``JWTAuth`` opens the PEM private key file in ``'rb'`` mode.
+
+1.5.2 (2016-05-19)
 ++++++++++++++++++
 
 - Bugfix so that ``OAuth2`` always has the correct tokens after a call to ``refresh()``.
diff --git a/boxsdk/auth/jwt_auth.py b/boxsdk/auth/jwt_auth.py
index 2d81697..266fff2 100644
--- a/boxsdk/auth/jwt_auth.py
+++ b/boxsdk/auth/jwt_auth.py
@@ -1,6 +1,6 @@
 # coding: utf-8
 
-from __future__ import unicode_literals
+from __future__ import absolute_import, unicode_literals
 
 from datetime import datetime, timedelta
 import random
@@ -95,7 +95,7 @@ def __init__(
             refresh_token=None,
             network_layer=network_layer,
         )
-        with open(rsa_private_key_file_sys_path) as key_file:
+        with open(rsa_private_key_file_sys_path, 'rb') as key_file:
             self._rsa_private_key = serialization.load_pem_private_key(
                 key_file.read(),
                 password=rsa_private_key_passphrase,
@@ -182,6 +182,7 @@ def authenticate_instance(self):
         :rtype:
             `unicode`
         """
+        self._user_id = None
         return self._auth_with_jwt(self._enterprise_id, 'enterprise')
 
     def _refresh(self, access_token):
diff --git a/boxsdk/version.py b/boxsdk/version.py
index 9f6ca5f..e4cd37c 100644
--- a/boxsdk/version.py
+++ b/boxsdk/version.py
@@ -3,4 +3,4 @@
 from __future__ import unicode_literals, absolute_import
 
 
-__version__ = '1.5.2'
+__version__ = '1.5.3'


Test patch:
diff --git a/test/unit/auth/test_jwt_auth.py b/test/unit/auth/test_jwt_auth.py
index a117850..c65af57 100644
--- a/test/unit/auth/test_jwt_auth.py
+++ b/test/unit/auth/test_jwt_auth.py
@@ -73,7 +73,7 @@ def jwt_auth_init_mocks(
     }
 
     mock_network_layer.request.return_value = successful_token_response
-    key_file_read_data = 'key_file_read_data'
+    key_file_read_data = b'key_file_read_data'
     with patch('boxsdk.auth.jwt_auth.open', mock_open(read_data=key_file_read_data), create=True) as jwt_auth_open:
         with patch('cryptography.hazmat.primitives.serialization.load_pem_private_key') as load_pem_private_key:
             oauth = JWTAuth(
@@ -88,7 +88,7 @@ def jwt_auth_init_mocks(
                 jwt_key_id=jwt_key_id,
             )
 
-            jwt_auth_open.assert_called_once_with(sentinel.rsa_path)
+            jwt_auth_open.assert_called_once_with(sentinel.rsa_path, 'rb')
             jwt_auth_open.return_value.read.assert_called_once_with()  # pylint:disable=no-member
             load_pem_private_key.assert_called_once_with(
                 key_file_read_data,