How to deocde JWT in Flutter? - dart

I want to decode JWT token in my mobile app.
I followed this method. https://stackoverflow.com/a/52021206/11065582
but output is,
{"site_id":"2","isActualNSolutionAvailable":"True","isCauseNEffectsAvailable":"True","isServiceCenterAvailable":"True","user_id":"190","employee_id":"36","user_name":"...","userPassword":"o+2r8b/9k9i75j4VE+9xNmJnQpbipT1lYRzzrciAXqWkE/jNzg6Qk5MWP16A==","userPWDSalt":"lbNmVWQGMsvlkhuX/YN6P6mobkC0L+1fgFtL6ttN3KI3/kXH/+OtBPff1A+WGfltiOmXf3Nbs2ewItPHhkrmHask+++UNNxSGm+xD/7Dz8vCxOzRTP5OE/Kf3LFXZwq1UmafhxIIYVua7m8eApulR+HwW47/RUKfJZvIZYjE80AYkoetYJmx4hdu+NBxItv1fyx1TGpMKbB+vY9F6CJK9xp76yrjtnzlctgJb5ID/xx/TMj9qLaBx+pAHGc3BZYRdlCXJYnHEasHTtDk2RoYvnv24iQpS5Q==","exp":1551332124,"iss":"sl.com","aud":"sl.com"}
How do I get only site_id?

based on the way you added you do the following(check the _decodeJWT method):
Map<String, dynamic> parseJwt(String token) {
final parts = token.split('.');
if (parts.length != 3) {
throw Exception('invalid token');
}
final payload = _decodeBase64(parts[1]);
final payloadMap = json.decode(payload);
if (payloadMap is! Map<String, dynamic>) {
throw Exception('invalid payload');
}
return payloadMap;
}
_decodeJwt(String token){
Map<String,dynamic> tokenDecoded = parseJWT(token);
String siteId = tokenDecoded['site_id'];
}

Related

How to call the serialization method from a Generic

Disk Cache with Generics
I am a programmer who comes from JavaScript and PHP, and am developing an App on Flutter, and am having difficulty implementing a cache on the phone's internal storage.
I would like to understand and know if it is possible to create a Generic type class with serialization for JSON so that it can be stored on file.
I've done the Cache implementation in memory and it works fine, plus the implementation of Cache on Disk I'm having difficulty.
Code for Memory cache
class MemCache<T> extends Cache<T> {
Duration cacheValidDuration = Duration(minutes: 30);
DateTime lastFetchTime = DateTime.fromMillisecondsSinceEpoch(0);
RList<T> allRecords = RList<T>();
//is updade cache
bool isShouldRefresh() {
return (null == allRecords ||
allRecords.isEmpty ||
null == lastFetchTime ||
lastFetchTime.isBefore(DateTime.now().subtract(cacheValidDuration)));
}
#override
Future<RList<T>> getAll() {
return Future.value(allRecords);
}
#override
Future<void> putAll(RList<T> objects) {
allRecords.addAll(objects);
lastFetchTime = DateTime.now();
}
#override
Future<void> putAllAsync(Future<RList<T>> objects) async {
allRecords = await objects;
}
}
Code for Disk Cache
How to call the serialization method from a Generic
class DiskCache<T> extends Cache<T> {
Duration cacheValidDuration = Duration(minutes: 30);
DateTime lastFetchTime = DateTime.fromMillisecondsSinceEpoch(0);
RList<T> allRecords = RList<T>();
//is update the cache
bool isShouldRefresh() {
return (null == allRecords ||
allRecords.isEmpty ||
null == lastFetchTime ||
lastFetchTime.isBefore(DateTime.now().subtract(cacheValidDuration)));
}
#override
Future<RList<T>> getAll() async {
await _readFromDisk();
return Future.value(allRecords);
}
#override
Future<void> putAll(RList<T> objects) async {
allRecords.addAll(objects);
lastFetchTime = DateTime.now();
await _writeToDisk();
}
#override
Future<void> putAllAsync(Future<RList<T>> objects) async {
allRecords = await objects;
lastFetchTime = DateTime.now();
await _writeToDisk();
}
//parth
Future<String> get _localPath async {
final directory = await getApplicationDocumentsDirectory();
return directory.path;
}
//file pointer
Future<File> get _localFile async {
final path = await _localPath;
return File('$path/allRecords.json');
}
//write to file
Future<File> _writeToDisk() async {
try {
File recordedFile;
if (allRecords != null) {
var map = allRecords.map((c) {
var item = c as ISerialization;
return item.toJson();
}).toList();
var jsonString = jsonEncode(map);
final file = await _localFile;
// Write the file
recordedFile = await file.writeAsString(jsonString);
}
return recordedFile;
} catch (e) {
print("writeToDisk: " + e.toString());
return null;
}
}
// ************************** issues on this part ******************
Future<RList<T>> _readFromDisk() async {
try {
final file = await _localFile;
// Read the file
String contents = await file.readAsString();
var parsedJson = jsonDecode(contents);
if (allRecords == null) {
allRecords = RList<T>();
}
allRecords.clear();
for (var item in parsedJson) {
// ************************** issues on this part ******************
print(T.fromMap(item));
allRecords.add(T.fromMap(item));
}
return allRecords;
} catch (e) {
print("readFromDisk: " + e.toString());
return null;
}
}
}
Error: The method 'fromMap' isn't defined for the class 'Type'.
- 'Type' is from 'dart:core'.
Try correcting the name to the name of an existing method, or defining a method named 'fromMap'.
allRecords.add(T.fromMap(item));
^^^^^^^

can built_value deserialize generics like this?

all my JSON data contains status(int), msg(String), and data(any Type). Because I'm come from java ,I want use generics。I'm writing a deserialize for a top generics with built_value, but failed.
I have try this
https://github.com/google/built_value.dart/blob/master/end_to_end_test/test/generics_serializer_test.dart.
But do not really understand.
There follows my code:
abstract class GenericValue<T>
implements Built<GenericValue<T>, GenericValueBuilder<T>> {
T get data;
int get status;
String get msg;
GenericValue._();
static Serializer<GenericValue> get serializer => _$genericValueSerializer;
factory GenericValue([updates(GenericValueBuilder<T> b)]) =
_$GenericValue<T>;
}
abstract class UserInfo implements Built<UserInfo, UserInfoBuilder> {
static Serializer<UserInfo> get serializer => _$userInfoSerializer;
String get id;
String get email;
UserInfo._();
factory UserInfo([updates(UserInfoBuilder b)]) = _$UserInfo;
}
GenericValue<UserInfo> parseUserInfo(String jsonStr) {
final parsed = json.jsonDecode(jsonStr);
final specifiedType = const FullType(GenericValue, [FullType(UserInfo)]);
final serializersWithBuilder = (standardSerializers.toBuilder()
..addBuilderFac`enter code here`tory(specifiedType, () => GenericValueBuilder<UserInfo>
()))
.build();
Response<UserInfo> response = serializersWithBuilder.deserialize(parsed,
specifiedType: specifiedType);
return response;
}
but result is: Invalid argument(s): Unknown type on deserialization. Need either specifiedType or discriminator field.
how can it do it in right way, to deserialize JSON data like this.
String toJsonUserInfo() {
final specifiedType = const FullType(GenericValue, [FullType(UserInfo)]);
final serializersWithBuilder = (standardSerializers.toBuilder()
..addBuilderFactory(
specifiedType, () => GenericValueBuilder<UserInfo>()))
.build();
return json.encode(
serializersWithBuilder.serialize(this, specifiedType: specifiedType));
}
static GenericValue<UserInfo> fromJsonUserInfo(String jsonString) {
final specifiedType = const FullType(GenericValue, [FullType(UserInfo)]);
final serializersWithBuilder = (standardSerializers.toBuilder()
..addBuilderFactory(
specifiedType, () => GenericValueBuilder<UserInfo>()))
.build();
return serializersWithBuilder.deserialize(json.decode(jsonString),
specifiedType: specifiedType);
}
it works.

JWT token parse

please tell me how correct parse JWT token.
I needed get roles...
static Authentication getAuthentication(HttpServletRequest request) {
String token = request.getHeader(HEADER_STRING);
if (token != null) {
// parse the token.
String user = Jwts.parser()
.setSigningKey(SECRET)
.parseClaimsJws(token.replace(TOKEN_PREFIX, ""))
.getBody()
.getSubject();
Claims claims = Jwts.parser()
.setSigningKey(SECRET)
.parseClaimsJws(token.replace(TOKEN_PREFIX, ""))
.getBody();
List<String> roles = (ArrayList<String>)claims.get("roles");
System.out.println("ROLE IS: " + roles);
return user != null ?
new UsernamePasswordAuthenticationToken(user, null, Collections.emptyList()) :
null;
}
return null;
}
output ROLE IS: [{authority=ROLE_ADMIN}, {authority=ROLE_USER}
How correct i can doing cast to Collection for use as parameter in UsernamePasswordAuthenticationToken.
Thank you.
So the problem was solved...
List<String> roles = (ArrayList)claims.get("roles");
for (Object role:roles){
HashMap<String,String> map = (HashMap<String,String>)role;
List<String> list = new ArrayList<>();
list.addAll(map.values());
for (String item: list) {
grantedAuthorityList = AuthorityUtils.createAuthorityList(item);
}

Add STOMP header without recreating Message on ChannelInterceptorAdapter

I need to add header to a STOMP message currently it is working as below but i am recreating the message , is it possible to just add native header without having to recreate the message for performance .
public class MyChannelInterceptor extends ChannelInterceptorAdapter {
#Override
public Message<?> preSend(Message<?> message, MessageChannel channel) {
StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message);
StompCommand command = accessor.getCommand();
if(command != null) {
log.debug("Receiving msg {} from {}",command,accessor.getUser().getName());
if(command == StompCommand.SEND) {
log.debug("Adding expires header to msg {} from {}",command,accessor.getUser().getName());
String ttlString = accessor.getFirstNativeHeader("ttl");
long ttl = 30000;
try {
ttl = Long.parseLong(ttlString);
}
catch(Exception ex) {
log.error("TTL header received but not in correct format {}",ttlString);
}
accessor.addNativeHeader("expires", Long.toString(System.currentTimeMillis() + ttl));
return MessageBuilder.createMessage(message.getPayload(), accessor.getMessageHeaders());
}
}
return message;
}
}
This is what i was looking for
StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
The above code will get the actual StompHeaderAccessor of the message so if you manipulate the native headers they are directly reflected on the message while
StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message);
will get a clone of the headers and you have to create a new message with the new cloned headers
full fixed code below
#Override
public Message<?> preSend(Message<?> message, MessageChannel channel) {
StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
// StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message);
if(accessor != null) {
StompCommand command = accessor.getCommand();
if(command != null) {
log.debug("Receiving msg {} from {}",command,accessor.getUser().getName());
if(command == StompCommand.SEND) {
log.debug("Adding expires header to msg {} from {}",command,accessor.getUser().getName());
String ttlString = accessor.getFirstNativeHeader("ttl");
long ttl = 30000;
if(ttlString != null) {
try {
ttl = Long.parseLong(ttlString);
}
catch(Exception ex) {
log.error("TTL header received but not in correct format {}",ttlString);
}
}
accessor.addNativeHeader("expires", Long.toString(System.currentTimeMillis() + ttl));
// I don't need any more to create a new message
//return MessageBuilder.createMessage(message.getPayload(), accessor.getMessageHeaders());
}
}
}
return message;
}
Since addNativeHeader succeeds, that indicates the message is still mutable - see addNativeHeader().
In any case, since the NATIVE_HEADERS message header is a MultiValueMap-valued header, you can update the header contents in-place.
Hence, there is no need to create a new message.
You would have to create a new message if you add a new header to the message itself (rather than updating the mutable contents of an existing header).
EDIT
I just ran a test; as long as the message is still mutable, you can change it...
#Test
public void test() {
Map<String, Object> map = new HashMap<String, Object>();
MutableMessageHeaders headers = new MutableMessageHeaders(map);
Message<String> message = MessageBuilder.createMessage("foo", headers);
StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message);
accessor.addNativeHeader("foo", "bar");
System.out.println(message.getHeaders().get(NativeMessageHeaderAccessor.NATIVE_HEADERS));
accessor.setImmutable();
try {
accessor.addNativeHeader("baz", "qux");
fail("expected IllegalStateException");
}
catch (IllegalStateException e) {
}
}
That said, are you experiencing a performance problem or is this just a perceived issue. Message creation is not expensive.

How to implement dynamic properties in Dart?

I would like to be able to back a dynamic property with a Map using a lookup in noSuchMethod(). However the latest changes makes the incoming property reference name unavailable. I can understand the minification scenario requiring us to use Symbols rather than Strings for names, but this makes implementing serializable dynamic properties difficult. Anyone have good ideas on how to approach this problem?
I can't use String names since the String names are not fixed between calls to the minifier. (This would completely break serialization)
You can access the original name with MirrorSystem.getName(symbol)
So a dynamic class could look like :
import 'dart:mirrors';
class A {
final _properties = new Map<String, Object>();
noSuchMethod(Invocation invocation) {
if (invocation.isAccessor) {
final realName = MirrorSystem.getName(invocation.memberName);
if (invocation.isSetter) {
// for setter realname looks like "prop=" so we remove the "="
final name = realName.substring(0, realName.length - 1);
_properties[name] = invocation.positionalArguments.first;
return;
} else {
return _properties[realName];
}
}
return super.noSuchMethod(invocation);
}
}
main() {
final a = new A();
a.i = 151;
print(a.i); // print 151
a.someMethod(); // throws
}
You could do something like this:
import 'dart:json' as json;
main() {
var t = new Thingy();
print(t.bob());
print(t.jim());
print(json.stringify(t));
}
class Thingy {
Thingy() {
_map[const Symbol('bob')] = "blah";
_map[const Symbol('jim')] = "oi";
}
final Map<Symbol, String> _map = new Map<Symbol, String>();
noSuchMethod(Invocation invocation) {
return _map[invocation.memberName];
}
toJson() => {
'bob': _map[const Symbol('bob')],
'jim': _map[const Symbol('jim')]};
}
Update - dynamic example:
import 'dart:json' as json;
main() {
var t = new Thingy();
t.add('bob', 'blah');
t.add('jim', 42);
print(t.bob());
print(t.jim());
print(json.stringify(t));
}
class Thingy {
final Map<Symbol, String> _keys = new Map<Symbol, String>();
final Map<Symbol, dynamic> _values = new Map<Symbol, dynamic>();
add(String key, dynamic value) {
_keys[new Symbol(key)] = key;
_values[new Symbol(key)] = value;
}
noSuchMethod(Invocation invocation) {
return _values[invocation.memberName];
}
toJson() {
var map = new Map<String, dynamic>();
_keys.forEach((symbol, name) => map[name] = _values[symbol]);
return map;
}
}
If you only need "dynamic properties", it should be enough to use Symbols as keys in the Map. If you also want to serialize that map, then you need to keep track of the original String names and use those for serialization. When deserializing, you'd have to create new Symbols from those Strings.
Note that all these scenarios (and basically everything that involves new Symbol) require a compiler to create a mapping of original names to the minified ones and put this mapping into the program, which of course makes it bigger.
Thanks for the solution of #Alexandre Ardhuin, I made some modification to make it runnable.
import 'dart:mirrors';
class object {
final _properties = new Map<String, Object>();
object();
object.from(Map<String, Object> initial) {
initial.entries.forEach((element) => _properties[element.key] = element.value);
}
noSuchMethod(Invocation invocation) {
if (invocation.isAccessor) {
final realName = MirrorSystem.getName(invocation.memberName);
if (invocation.isSetter) {
// for setter realname looks like "prop=" so we remove the "="
final name = realName.substring(0, realName.length - 1);
_properties[name] = invocation.positionalArguments.first;
return;
} else {
return _properties[realName];
}
}
return super.noSuchMethod(invocation);
}
#override
String toString() {
return _properties.toString();
}
}
main() {
// we can't use var or object type here, because analysis will consider
// https://dart.dev/tools/diagnostic-messages#undefined_setter
// The setter 'i' isn't defined for the type 'object'
// So dynamic is required here!
dynamic a = object.from({'a': 123, 'b': 234});
a.i = 151;
print(a); // print {a: 123, b: 234, i: 151}
try {
a.someMethod(); // throws NoSuchMethodError
} catch (e) {
print(e);
}
}

Resources