ios - invalid - jwt java
NSData no aceptará una cadena codificada en base64 válida (5)
Aquí hay una solución que rellena adecuadamente la cadena Base-64 y funciona en iOS 4+:
NSData + Base64.h
@interface NSData (Base64)
/**
Returns a data object initialized with the given Base-64 encoded string.
@param base64String A Base-64 encoded NSString
@returns A data object built by Base-64 decoding the provided string. Returns nil if the data object could not be decoded.
*/
- (instancetype) initWithBase64EncodedString:(NSString *)base64String;
/**
Create a Base-64 encoded NSString from the receiver''s contents
@returns A Base-64 encoded NSString
*/
- (NSString *) base64EncodedString;
@end
NSData + Base64.m
@interface NSString (Base64)
- (NSString *) stringPaddedForBase64;
@end
@implementation NSString (Base64)
- (NSString *) stringPaddedForBase64 {
NSUInteger paddedLength = self.length + (self.length % 3);
return [self stringByPaddingToLength:paddedLength withString:@"=" startingAtIndex:0];
}
@end
@implementation NSData (Base64)
- (instancetype) initWithBase64EncodedString:(NSString *)base64String {
return [self initWithBase64Encoding:[base64String stringPaddedForBase64]];
}
- (NSString *) base64EncodedString {
return [self base64Encoding];
}
@end
Estoy implementando la autenticación JSON Web Token en el lado del cliente iOS (7). Está funcionando muy bien. Mi aplicación recibe tokens y puede hacer llamadas autenticadas a mi servidor con ellos.
Ahora, quiero que el código del lado del cliente compruebe la fecha de caducidad en el token para que pueda saber cuándo volver a autenticarse. La comprobación de la fecha de caducidad en un token de autenticación JWT es sencilla. El token de autorización es 3 blobs JSON codificados en base64, separados por un ''.'' - La marca de tiempo de caducidad está en el blob central, en un campo llamado ext
. Son segundos desde la época de Unix.
Así que mi código se ve así:
- (NSDate*) expirationDate
{
if ( !_tokenAppearsValid ) return nil;
if ( !_parsedExpirationDate )
{
//
// Token is three base64 encoded payloads separated by ''.''
// The payload we want is the middle one, which is a JSON dict, with
// ''exp'' being the unix seconds timestamp of the expiration date
// Returning nil is appropriate if no ''exp'' is findable
//
NSArray *components = [self.token componentsSeparatedByString:@"."];
NSString *payload = components[1];
NSData* payloadJsonData = [[NSData alloc]
initWithBase64EncodedString:payload
options:NSDataBase64DecodingIgnoreUnknownCharacters];
NSError* jsonError = nil;
NSDictionary* payloadJson = [NSJSONSerialization JSONObjectWithData:payloadJsonData options:0 error:&jsonError];
if ( payloadJson )
{
if ( payloadJson[@"exp"] )
{
NSTimeInterval timestampSeconds = [payloadJson[@"exp"] doubleValue];
_expirationDate = [NSDate dateWithTimeIntervalSince1970:timestampSeconds];
}
}
_parsedExpirationDate = YES;
}
return _expirationDate;
}
El problema es simple. El blob base64 mediano, cuando es analizado por NSData -initWithBase64EncodedString es nil
- y eso es malo.
He comprobado el blob base64 y parece ser válido. El servidor está devolviendo datos ficticios por el momento, así que aquí hay un ejemplo de blob: eyJlbWFpbCI6ImZvb0BiYXIuYmF6IiwiYWNjb3VudElkIjoiMTIzNDUtNjc4OTAtYmFyLWJheiIsImV4cCI6MTM5MDkxNTAzNywiaWF0IjoxMzkwOTE0MTM3fQ
Se decodifica a:
{"email":"[email protected]","accountId":"12345-67890-bar-baz","exp":1390915037,"iat":1390914137}
Lo probé aquí: http://www.base64decode.org
He utilizado los métodos base64 de NSData en mi aplicación con éxito, no creo que esté haciendo nada particularmente roto aquí. ¡Pero soy todo oídos! ¿Algunas ideas?
Aunque la respuesta de Martin es correcta, aquí hay una manera rápida y correcta (!) De solucionar el problema:
NSString *base64String = @"<the token>";
NSUInteger paddedLength = base64String.length + (4 - (base64String.length % 4));
NSString* correctBase64String = [base64String stringByPaddingToLength:paddedLength withString:@"=" startingAtIndex:0];
Me enfrenté al mismo problema, pero lo resolví agregando ==
al final de la cadena
base64UserStr = NSString(format: "%@%@", base64UserStr,"==") as String
let decodedData = NSData(base64EncodedString: base64UserStr, options: NSDataBase64DecodingOptions.init(rawValue: 0))
if (decodedData != nil)
{
let decodedString = NSString(data: decodedData!, encoding: NSUTF8StringEncoding)
print("Base 64 decode string is /(decodedString)")
}
Esto definitivamente funcionará.
Tu cadena Base64 no es válida. Debe rellenarse con =
caracteres para tener una longitud que sea múltiplo de 4. En su caso: "eyJlbWFp....MTM3fQ=="
.
Con este relleno, initWithBase64EncodedString
decodifica la cadena Base64 correctamente.
Una versión rápida de la respuesta de Paul.
func paddedBase64EncodedString(encodedString: String) -> String
{
let encodedStringLength = encodedString.characters.count
let paddedLength = encodedStringLength + (4 - (encodedStringLength % 4))
let paddedBase64String = encodedString.stringByPaddingToLength(paddedLength,
withString: "=",
startingAtIndex: 0)
return paddedBase64String
}